Create a service SAS for a blob with .NET

A shared access signature (SAS) enables you to grant limited access to containers and blobs in your storage account. When you create a SAS, you specify its constraints, including which Azure Storage resources a client is allowed to access, what permissions they have on those resources, and how long the SAS is valid.

Every SAS is signed with a key. You can sign a SAS in one of two ways:

  • With a key created using Microsoft Entra credentials. A SAS that is signed with Microsoft Entra credentials is a user delegation SAS. A client that creates a user delegation SAS must be assigned an Azure RBAC role that includes the Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey action. To learn more, see Create a user delegation SAS.
  • With the storage account key. Both a service SAS and an account SAS are signed with the storage account key. The client that creates a service SAS must either have direct access to the account key or be assigned the Microsoft.Storage/storageAccounts/listkeys/action permission. To learn more, see Create a service SAS or Create an account SAS.

Note

A user delegation SAS offers superior security to a SAS that is signed with the storage account key. Microsoft recommends using a user delegation SAS when possible. For more information, see Grant limited access to data with shared access signatures (SAS).

This article shows how to use the storage account key to create a service SAS for a blob with the Azure Blob Storage client library for .NET.

About the service SAS

A service SAS is signed with the account access key. You can use the StorageSharedKeyCredential class to create the credential that is used to sign the service SAS.

You can also use a stored access policy to define the permissions and duration of the SAS. If the name of an existing stored access policy is provided, that policy is associated with the SAS. To learn more about stored access policies, see Define a stored access policy. If no stored access policy is provided, the code examples in this article show how to define permissions and duration for the SAS.

Create a service SAS for a blob

The following code example shows how to create a service SAS for a blob resource. First, the code verifies that the BlobClient object is authorized with a shared key credential by checking the CanGenerateSasUri property. Then, it generates the service SAS via the BlobSasBuilder class, and calls GenerateSasUri to create a service SAS URI based on the client and builder objects.

public static async Task<Uri> CreateServiceSASBlob(
    BlobClient blobClient,
    string storedPolicyName = null)
{
    // Check if BlobContainerClient object has been authorized with Shared Key
    if (blobClient.CanGenerateSasUri)
    {
        // Create a SAS token that's valid for one day
        BlobSasBuilder sasBuilder = new BlobSasBuilder()
        {
            BlobContainerName = blobClient.GetParentBlobContainerClient().Name,
            BlobName = blobClient.Name,
            Resource = "b"
        };

        if (storedPolicyName == null)
        {
            sasBuilder.ExpiresOn = DateTimeOffset.UtcNow.AddDays(1);
            sasBuilder.SetPermissions(BlobContainerSasPermissions.Read);
        }
        else
        {
            sasBuilder.Identifier = storedPolicyName;
        }

        Uri sasURI = blobClient.GenerateSasUri(sasBuilder);

        return sasURI;
    }
    else
    {
        // Client object is not authorized via Shared Key
        return null;
    }
}

Use a service SAS to authorize a client object

The following code example shows how to use the service SAS to authorize a BlobClient object. This client object can be used to perform operations on the blob resource based on the permissions granted by the SAS.

First, create a BlobServiceClient object signed with the account access key:

string accountName = "<storage-account-name>";
string accountKey = "<storage-account-key";
StorageSharedKeyCredential storageSharedKeyCredential =
    new(accountName, accountKey);
BlobServiceClient blobServiceClient = new BlobServiceClient(
    new Uri($"https://{accountName}.blob.core.windows.net"),
    storageSharedKeyCredential);

Then, generate the service SAS as shown in the earlier example and use the SAS to authorize a BlobClient object:

// Create a Uri object with a service SAS appended
BlobClient blobClient = blobServiceClient
    .GetBlobContainerClient("sample-container")
    .GetBlobClient("sample-blob.txt");
Uri blobSASURI = await CreateServiceSASBlob(blobClient);

// Create a blob client object representing 'sample-blob.txt' with SAS authorization
BlobClient blobClientSAS = new BlobClient(blobSASURI);

Define a stored access policy

A stored access policy provides an additional level of control over a service-level shared access signature (SAS) on the server side. Establishing a stored access policy serves to group shared access signatures and to provide additional restrictions for signatures that are bound by the policy.

You can use a stored access policy to change the start time, expiry time, or permissions for a signature. You can also use a stored access policy to revoke a signature after it has been issued. This section focuses on blob containers, but stored access policies are also supported for file shares, queues, and tables.

To manage stored access policies on a container resource, call one of the following methods from a BlobContainerClient object:

Create or modify a stored access policy

You can set a maximum of five access policies on a resource at a time. Each SignedIdentifier field, with its unique Id field, corresponds to one access policy. Trying to set more than five access policies at one time causes the service to return status code 400 (Bad Request).

The following code example shows how to create two stored access policies on a container resource:

public static async Task CreateStoredAccessPolicyAsync(BlobContainerClient containerClient)
{
    // Create a stored access policy with read and write permissions, valid for one day
    List<BlobSignedIdentifier> signedIdentifiers = new List<BlobSignedIdentifier>
    {
        new BlobSignedIdentifier
        {
            Id = "sample-read-write-policy",
            AccessPolicy = new BlobAccessPolicy
            {
                StartsOn = DateTimeOffset.UtcNow,
                ExpiresOn = DateTimeOffset.UtcNow.AddDays(1),
                Permissions = "rw"
            }
        },
        new BlobSignedIdentifier
        {
            Id = "sample-read-policy",
            AccessPolicy = new BlobAccessPolicy
            {
                StartsOn = DateTimeOffset.UtcNow,
                ExpiresOn = DateTimeOffset.UtcNow.AddDays(1),
                Permissions = "r"
            }
        }
    };

    // Set the container's access policy
    await containerClient.SetAccessPolicyAsync(permissions: signedIdentifiers);
}

You can also modify an existing policy. The following code example shows how to modify a single stored access policy to update the policy expiration date:

public static async Task ModifyStoredAccessPolicyAsync(BlobContainerClient containerClient)
{
    BlobContainerAccessPolicy accessPolicy = await containerClient.GetAccessPolicyAsync();
    List<BlobSignedIdentifier> signedIdentifiers = accessPolicy.SignedIdentifiers.ToList();

    // Modify the expiration date a single policy
    var samplePolicy = signedIdentifiers.FirstOrDefault(item => item.Id == "sample-read-policy");
    samplePolicy.AccessPolicy.PolicyExpiresOn = DateTimeOffset.UtcNow.AddDays(7);

    // Update the container's access policy
    await containerClient.SetAccessPolicyAsync(permissions: signedIdentifiers);
}

Revoke or delete a stored access policy

To revoke a stored access policy, you can delete it, rename it by changing the signed identifier, or change the expiry time to a value in the past. Changing the signed identifier breaks the associations between any existing signatures and the stored access policy. Changing the expiry time to a value in the past causes any associated signatures to expire. Deleting or modifying the stored access policy immediately affects all of the shared access signatures associated with it.

The following code example shows how to revoke a policy by changing the Id property for the signed identifier:

public static async Task RevokeStoredAccessPolicyAsync(BlobContainerClient containerClient)
{
    BlobContainerAccessPolicy accessPolicy = await containerClient.GetAccessPolicyAsync();
    List<BlobSignedIdentifier> signedIdentifiers = accessPolicy.SignedIdentifiers.ToList();

    // Revoke a single policy by changing its name
    var samplePolicy = signedIdentifiers.FirstOrDefault(item => item.Id == "sample-read-policy");
    samplePolicy.Id = "sample-read-policy-revoke";

    // Update the container's access policy
    await containerClient.SetAccessPolicyAsync(permissions: signedIdentifiers);
}

You can also remove all access policies from a container resource by calling SetAccessPolicyAsync with an empty permissions parameter. The following example shows how to delete all stored access policies from a specified container:

public static async Task DeleteStoredAccessPolicyAsync(BlobContainerClient containerClient)
{
    // Remove all stored access policies for the container resource
    await containerClient.SetAccessPolicyAsync();
}

Resources

To learn more about creating a service SAS using the Azure Blob Storage client library for .NET, see the following resources.

Client library resources

See also