When working with Azure Storage Blobs in .NET, you will often need to generate Shared Access Signature (SAS) URIs to provide temporary, secure access to your blob resources.
However, if you're using
DefaultAzureCredential for authentication we cannot simply call GenerateSasUri() on a BlobClient
instance.
BlobServiceClient blobServiceClient = new BlobServiceClient(
new Uri($"https://{storageAccountName}.blob.core.windows.net"),
new DefaultAzureCredential());
BlobClient blobClient = blobServiceClient
.GetBlobContainerClient(containerName)
.GetBlobClient(blobName);
// Throws exception: System.ArgumentNullException: Value cannot be null. (Parameter 'sharedKeyCredential')
Uri sasUri = blobClient.GenerateSasUri(BlobSasPermissions.Read, DateTimeOffset.UtcNow.AddMinutes(5));
That's because GenerateSasUri() requires SharedKeyCredential to sign the SAS token. When using DefaultAzureCredential, you don't have access to the storage account key.
The Quick (But Not Ideal) Workaround
For faster development and testing, many developers (myself included) have
resorted to using connection strings with account keys:
BlobServiceClient blobServiceClient = new BlobServiceClient(
$"DefaultEndpointsProtocol=https;AccountName={storageAccountName};AccountKey={accountKey};EndpointSuffix=core.windows.net");
BlobClient blobClient = blobServiceClient
.GetBlobContainerClient(containerName)
.GetBlobClient(blobName);
// Now GenerateSasUri() works
Uri sasUri = blobClient.GenerateSasUri(BlobSasPermissions.Read, DateTimeOffset.UtcNow.AddMinutes(5));
The Best Approach: User Delegation Keys
The recommended solution is to use User Delegation Keys. This approach
allows you to generate SAS tokens using Azure AD credentials instead of
storage account keys.
BlobServiceClient blobServiceClient = new BlobServiceClient(
new Uri($"https://{storageAccountName}.blob.core.windows.net"),
new DefaultAzureCredential());
BlobClient blobClient = blobServiceClient
.GetBlobContainerClient(containerName)
.GetBlobClient(blobName);
// Define the SAS validity period
var startsOn = DateTimeOffset.UtcNow.AddMinutes(-1);
var expiresOn = DateTimeOffset.UtcNow.AddMinutes(5);
// Build the SAS token configuration
var sasBuilder = new BlobSasBuilder
{
BlobContainerName = containerName,
BlobName = blobName,
Resource = "b",
StartsOn = startsOn,
ExpiresOn = expiresOn,
};
sasBuilder.SetPermissions(BlobSasPermissions.Read);
// Get user delegation key from Azure AD (uses your Azure AD identity)
Response<UserDelegationKey> userDelegationKey =
await blobServiceClient.GetUserDelegationKeyAsync(startsOn, expiresOn);
// Generate SAS URI using user delegation key
var blobUriBuilder = new BlobUriBuilder(blobClient.Uri)
{
Sas = sasBuilder.ToSasQueryParameters(
userDelegationKey.Value,
blobServiceClient.AccountName)
};
Uri sasUri = blobUriBuilder.ToUri();
And note this requires the identity to have Permission: Storage Blob Delegator.
Hope this helps.
Happy Coding.