question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Cannot generate SAS token for Blob using GetSharedAccessSignature(policy) and Azure Managed Identity.

See original GitHub issue

Which service(blob, file, queue, table) does this issue concern?

Microsoft.Azure.Storage.Blob;

Which version of the SDK was used?

Azure Tools 2.9 Microsoft.Azure.Storage.Blob 10.0.3 Microsoft.Azure.Services.App.Authentication 1.2.0-preview3

Which platform are you using? (ex: .NET Core 2.1)

.NET Core 2.2

What problem was encountered?

Cannot generate SAS token when using Managed Identity. I have App Service on Azure trying to generate SAS token using the RBAC role Assignment. For the time being, I even assigned the identity as “Owner” role but still it cannot generate SAS token. It says, I need a Account Key Credentials. If I have to provide Account Key in the code, then doesn’t it defeat the purpose of Managed Identity. We want to avoid using Storage Key in our solution and use Managed Identity.

Below is the error. 2019-05-22 15:15:19.283 +00:00 [Error] Microsoft.AspNetCore.Server.IIS.Core.IISHttpServer: Connection ID "16861477006485750114", Request ID "80000165-0000-ea00-b63f-84710c7967bb": An unhandled exception was thrown by the application.System.InvalidOperationException: Cannot create Shared Access Signature unless Account Key credentials are used.at Microsoft.Azure.Storage.Blob.CloudBlob.GetSharedAccessSignature(SharedAccessBlobPolicy policy,

How can we reproduce the problem in the simplest way?

const string blobName = “https://yourcontainer.blob.core.windows.net/images/image1.jpg”;

        var azureServiceTokenProvider = new AzureServiceTokenProvider();
        string accessToken = (azureServiceTokenProvider.GetAccessTokenAsync("https://storage.azure.com/")).Result;

  
        AccountKeyCredentials accountKeyCredentials;

        TokenCredential tokenCredential = new TokenCredential(accessToken);

        StorageCredentials storageCredentials = new StorageCredentials(tokenCredential);

        
        CloudBlockBlob blob = new CloudBlockBlob(new Uri(blobName),
                                                    storageCredentials);
     
        SharedAccessBlobPolicy policy = new SharedAccessBlobPolicy()
        {                
            Permissions = SharedAccessBlobPermissions.Read,                                
            SharedAccessExpiryTime = DateTime.UtcNow.AddDays(24),
        };

        var sasToken = blob.GetSharedAccessSignature(policy);

Have you found a mitigation/solution?

No.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:21
  • Comments:17

github_iconTop GitHub Comments

6reactions
tomgallardcommented, Aug 12, 2019

@tomgallard I can’t get it to work. GetUserDelegationKey throws “Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.” in GetUserDelegationKey. Note that I’m using a SAS to a container, not the account.

Code:

Microsoft.Azure.Storage.Blob.CloudBlobContainer container = new Microsoft.Azure.Storage.Blob.CloudBlobContainer(new Uri("url+sas goes here"));
var blockBlob = container.GetBlockBlobReference("folder/file.txt");
//The following line fails with message: "Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature."
var delegationKey = blockBlob.ServiceClient.GetUserDelegationKey(DateTimeOffset.UtcNow.AddMinutes(-1), DateTimeOffset.UtcNow.AddMinutes(15));
var sas = blockBlob.GetUserDelegationSharedAccessSignature(delegationKey, new Microsoft.Azure.Storage.Blob.SharedAccessBlobPolicy()
                    {
                        SharedAccessStartTime = DateTime.UtcNow.AddHours(-1),
                        SharedAccessExpiryTime = DateTime.UtcNow.AddHours(16),
                        Permissions = Microsoft.Azure.Storage.Blob.SharedAccessBlobPermissions.Read
                    });
return blockBlob.Uri.ToString() + sas;

Any ideas?

Yes- before you start accessing containers you need to instantiate a blob client passing in a set of TokenCredentials- something like t his:

AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
           //this comes from local cache if not expired- not expensive, no need to cache
           
string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync("https://storage.azure.com/");
TokenCredential tokenCredential = new TokenCredential(accessToken);
StorageCredentials storageCredentials = new StorageCredentials(tokenCredential);
var cloudBlobClient = new CloudBlobClient(new StorageUri(new Uri($"https://{_accountName.ToLower()}.blob.core.windows.net")), storageCredentials);
var container = cloudBlobClient.GetContainerReference("containerName")
3reactions
ekshacommented, May 18, 2021

@Xiaoxin4396 Its been a long time since I probably fixed it, so I don’t remember exactly the cause of the exception. It probably was related to usin GetSharedAccessSignature method, rather I used BlobSasBuilder in my final code. I am sharing the code, which is running fine currently, hope it helps you in some way

         
        private static string connectionString = ConfigurationManager.AppSettings["AzureStorageConnectionString"];
        private static BlobContainerClient containerClient;
        private static string accountName = ConfigurationManager.AppSettings["AzureStorageAccountName"];
        private static string accountKey = ConfigurationManager.AppSettings["AzureStorageAccountKey"];

        /**
         *  Generates PreSigned URL for sharing the bucket objects
         */
        public string GeneratePreSignedURLAzure(string bucketName, string objectKey, int timeInMinutes = 5)
        {
            // Construct the blob endpoint from the account name.
            string blobEndpoint = string.Format("https://{0}.blob.core.windows.net", accountName);

            StorageSharedKeyCredential sharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey);

            // Create a new Blob service client with Azure AD credentials.  
            BlobServiceClient blobClient = new BlobServiceClient(connectionString);

            // Create a SAS token that's valid for one hour.
            BlobSasBuilder sasBuilder = new BlobSasBuilder()
            {
                BlobContainerName = bucketName,
                BlobName = objectKey,
                Resource = "b",
            };

            string storedPolicyName = null;

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

            // Use the key to get the SAS token.
            string sasToken = sasBuilder.ToSasQueryParameters(sharedKeyCredential).ToString();

            Console.WriteLine("SAS token for blob container is: {0}", sasToken);
            Console.WriteLine();

            return $"{blobEndpoint}/{bucketName}/{objectKey}?{sasToken}";
        }

Read more comments on GitHub >

github_iconTop Results From Across the Web

Create SAS tokens for storage containers - Azure
How to create Shared Access Signature tokens (SAS) for containers and blobs with Microsoft Storage Explorer and the Azure portal.
Read more >
Getting Error while Creating SAS Token for Azure Storage ...
1 Answer. Based on this Github issue , you will need to assign Storage data roles to your MSI in order to generate...
Read more >
Generate SAS Token For Azure Blob Storage Using ...
This article demonstrates how to generate user delegation shared access signature (SAS) tokens for an Azure Blob. As we know, managed identities ......
Read more >
Securely Access Azure Blob Storage Containers in C# with ...
Hi Everyone, Azure Blob Storage is a cloud storage service that allows ... In this video, we'll explore how to generate SAS tokens...
Read more >
How To Generate Sas Token In Azure
Select Get Shared Access Signature from the options. In this post I am focusing on the Azure Files service because I want to...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found