How to Secure User-Level Access to Azure Blob Storage Files

Mohamed, Rihan 60 Reputation points
2026-09-23T11:34:15.0833333+00:00

I am investigating secure file storage for an AI agent that generates Excel reports and stores them in Azure Blob Storage.

Currently, multiple users' files are stored in the same private container. I want to ensure that User A can only access User A's files and cannot view or download User B's files.

Questions:

What is the recommended Azure architecture for user-level file isolation?

Can Microsoft Entra Managed Identity, Azure RBAC/ABAC, and user-delegation SAS provide secure access to individual users' files?

How can I restrict SAS URLs so users can only access their own files?

What is the recommended way to structure blob paths and prevent cross-user access?

I am looking for a secure and practical implementation approach using Azure Blob Storage.

Azure Blob Storage
Azure Blob Storage

An Azure service that stores unstructured data in the cloud as blobs.

0 comments No comments

1 answer

Sort by: Most helpful
  1. Marcin Policht 109.6K Reputation points MVP Volunteer Moderator
    2026-09-23T12:09:40.9866667+00:00

    Consider using a private Blob Storage container with application-level authorization, Microsoft Entra Managed Identity, Azure RBAC, and short-lived user-delegation SAS. You do not need a separate container for every user. The AI agent/backend can use a system-assigned managed identity to access Blob Storage without storing credentials, while the application determines which authenticated user owns each file. Azure RBAC controls what the AI agent can do against the storage account, while the application's authorization logic provides the end-user isolation boundary. Azure ABAC can be added as a defense-in-depth control where its supported conditions fit the design, but it should not replace the application's ownership check.

    Start with a logical per-user blob namespace based on an immutable identifier such as the user's Microsoft Entra object ID or an application-generated UUID. For example, use users/{entra-object-id}/{file-id}.xlsx, such as users/8f3.../reports/4b72....xlsx. Avoid using display names or email addresses as the security boundary, and preferably use an unpredictable GUID for the file ID rather than relying solely on a user-supplied filename. Maintain an application-side ownership record such as fileId -> userObjectId -> blobName. This gives the backend an authoritative way to determine that a requested file actually belongs to the authenticated user.

    The AI agent's managed identity should be assigned an appropriate Azure Storage data-plane role, such as Storage Blob Data Contributor when it needs to create and modify reports, or a more restrictive role if its operations permit it. Storage Blob Data Owner should only be used when the application genuinely requires the additional permissions. The storage account should have anonymous/public blob access disabled, and the application should not use storage account keys for normal access. RBAC establishes the agent's permissions to Blob Storage; it does not automatically mean that User A can access only the blobs under User A's prefix.

    For end-user downloads, the backend should issue a short-lived user-delegation SAS for the specific blob after authenticating the user and verifying ownership. The flow is essentially User A -> Entra ID -> application/backend -> ownership check -> blob-specific user-delegation SAS -> Azure Blob Storage. The managed identity authenticates the backend to Azure and allows it to obtain a user-delegation key and construct the SAS. The SAS can then be returned to the user's browser so the browser downloads directly from Blob Storage without giving the user the application's storage credentials.

    The SAS should be scoped to the exact blob rather than the container. For example, if User A is authorized for users/A/report123.xlsx, generate the SAS for that blob with only the Read permission and a short expiration, such as 5–15 minutes where appropriate. Do not issue a container-level SAS simply because the user needs to download one of their reports, and do not grant List, Write, or Delete permissions unless they are specifically required. If User A modifies the URL to point to users/B/report456.xlsx, the SAS is still cryptographically bound to the originally authorized resource, so it cannot simply be repurposed to access User B's blob.

    The critical authorization check occurs before SAS generation. The backend must obtain User A's identity from the validated Entra authentication context rather than accepting a userId supplied by the client. It should then look up the requested file in its server-side metadata and verify that the recorded owner is User A. Only after that check succeeds should it construct the SAS for the corresponding blob. This prevents an attacker from simply changing a request from userA/report.xlsx to userB/report.xlsx. The application should also avoid allowing arbitrary client-supplied blob paths to flow directly into Blob Storage operations.

    The same model should be used for uploads. User A requests an upload, the backend authenticates User A, creates the blob name under User A's namespace, records the ownership relationship, and generates a short-lived SAS containing only the permissions required for that upload. The browser can then upload directly to Blob Storage. The AI agent can subsequently read or process the uploaded file using its managed identity. This keeps large Excel files off the application server while maintaining the authorization boundary.

    Do not give users a container-level SAS just so they can enumerate their own reports. If users need a list of their files, have the backend query application metadata for the authenticated user's object ID and return only that user's files. When the user selects one, the backend performs the ownership check and generates a short-lived SAS for that particular blob. This prevents users from discovering other users' filenames or blobs through Blob Storage listing operations.

    Azure ABAC can provide an additional authorization layer through role-assignment conditions where the required Blob Storage operations and attributes are supported. For example, blob index tags can be used in certain conditional RBAC scenarios. However, ABAC should be viewed as defense in depth rather than the primary mechanism for ordinary application-level user isolation. The application already knows the authenticated user's identity and the ownership relationship, making that server-side authorization check the clearest control for deciding whether a particular user should receive a SAS.

    You can also apply additional SAS restrictions such as HTTPS-only access and, where appropriate, an IP-address restriction. An IP restriction can reduce the usefulness of a leaked SAS from another network, but it should generally be treated as an optional additional control because users may legitimately move between networks, use VPNs, or access the service through changing public IP addresses. Short expiration times, exact-blob scope, minimal permissions, and HTTPS are the more fundamental controls.


    If the above response helps answer your question, remember to "Accept Answer" so that others in the community facing similar issues can easily find the solution. Your contribution is highly appreciated.

    hth

    Marcin

    Was this answer helpful?


Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.