Search code examples
c#.netazureazure-blob-storagesas-token

Azure Blob Storage SAS URL generation issue with managed identity


I am encountering an issue when generating a Shared Access Signature (SAS) URL for a file in Azure Blob Storage using managed identity. The generated SAS URL contains a '+' sign in the signature field, which causes the error "Signature fields not well formed" when trying to use the URL for access.

public string GenerateSaS(string account,
                          string containerName,
                          string fileName,
                          int expiryTimeInMins)
{
    try
    {
        var tokenCredential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = Environment.GetEnvironmentVariable("<My CLient Id>") });
        BlobServiceClient blobServiceClient = new BlobServiceClient(new Uri($"https://{account}.blob.core.windows.net/"), tokenCredential);
        BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(containerName);

        // Check if the container exists
        if (!containerClient.Exists())
        {
            return null;
        }

        // Create a BlobSasBuilder instance
        var sharedPolicy = new BlobSasBuilder
        {
            StartsOn = DateTimeOffset.UtcNow,
            ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(expiryTimeInMins),
            ContentDisposition = $"attachment;filename={fileName}",
            BlobContainerName = containerName,
            BlobName = fileName,
            Resource = "b", // Blob-level access
            Protocol = SasProtocol.Https // Use HTTPS only
        };
        sharedPolicy.SetPermissions(BlobSasPermissions.Read | BlobSasPermissions.Write | BlobSasPermissions.Create);

        // Generate SAS token and create BlobUriBuilder
        BlobClient blobClient = containerClient.GetBlobClient(fileName);
        var blobUriBuilder = new BlobUriBuilder(blobClient.Uri)
        {
            Sas = sharedPolicy.ToSasQueryParameters(blobServiceClient.GetUserDelegationKey(DateTimeOffset.UtcNow.AddMinutes(-2), DateTimeOffset.UtcNow.AddMinutes(2)), blobServiceClient.AccountName)
        };

        // Convert BlobUriBuilder to URL string
        var url = blobUriBuilder.ToUri().ToString();

        return url;
    }
    catch (Exception ex)
    {
        // Handle exception
        throw ex;
    }
}

Signature sample in the url => sig=7SAJlSwRz8RNMQkEV4Y+hfIMEfVIRFapY49U/vqf4cI=

I tried diffrent ways to generate the url but no luck. I am expecting a working solution for this issue


Solution

  • Azure Blob Storage SAS URL generation issue with managed identity

    You can use the code below to generate the Azure Blob Storage SAS URL using .Net code.

    Code:

    using Azure.Identity;
    using Azure.Storage.Blobs;
    using Azure.Storage.Sas;
    
    namespace SAStoken
    {
        class Program
        {
            private static void Main()
            {
                var account = "venkat123";
                var containerName = "test";
                var fileName = "imp.png";
                var Credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = Environment.GetEnvironmentVariable("<My CLient Id>") });
                BlobServiceClient blobServiceClient = new BlobServiceClient(new Uri($"https://{account}.blob.core.windows.net/"), Credential);
                BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(containerName);
                BlobClient blobClient = containerClient.GetBlobClient(fileName);
    
                var userDelegationKey = blobServiceClient.GetUserDelegationKey(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(1));
    
                var sasBuilder = new BlobSasBuilder()
                {
                    BlobContainerName = blobClient.BlobContainerName,
                    BlobName = blobClient.Name,
                    Resource = "b", // b for blob, c for container
                    StartsOn = DateTimeOffset.UtcNow,
                    ExpiresOn = DateTimeOffset.UtcNow.AddHours(4),
                    Protocol = SasProtocol.Https
                };
                sasBuilder.SetPermissions(BlobSasPermissions.Read | BlobSasPermissions.Write | BlobSasPermissions.Create);
    
                BlobUriBuilder blobUriBuilder = new BlobUriBuilder(blobClient.Uri)
                {
                    // Specify the user delegation key.
                    Sas = sasBuilder.ToSasQueryParameters(userDelegationKey, blobServiceClient.AccountName)
                };
    
                Console.WriteLine("BlobSAS URI: {0}", blobUriBuilder);
            }
    
        }
    }
    

    Output:

    BlobSAS URI: https://venkat123.blob.core.windows.net/test/imp.png?skoid=6xxxxxx&sktid=72fxxxxxx-41af-91ab-2d7xxb47&skt=2024-04-29T07%3A16%3A33Z&ske=2024-04-30T07%3A16%3A33Z&sks=b&skv=2023-11-03&sv=2023-11-03&spr=https&st=2024-04-29T07%3A16%3A37Z&se=2024-04-29T11%3A16%3A37Z&sr=b&sp=rcw&sig=reHWCZ0lNDyBGxxxxxfH4Z3I7E%3D
    

    enter image description here

    Browser:

    enter image description here