Harry
Harry

Reputation: 3947

Azure Blob SAS Url returned from API authentication failed .net core

I am trying to return a SAS url to my frontend so I can redirect the user to that link and so they can download the file.

This is my code to create the SAS url

   private SasQueryParameters GenerateSaSCredentials(string containerName, string blobName) {


        //  Defines the resource being accessed and for how long the access is allowed.
        BlobSasBuilder blobSasBuilder = new() {
            StartsOn = DateTime.UtcNow.Subtract(TimeSpan.FromMinutes(10)),
            ExpiresOn = DateTime.UtcNow.Add(TimeSpan.FromMinutes(120)) + TimeSpan.FromSeconds(1),
            Resource = "b",
            BlobName = blobName,
            BlobContainerName = containerName
        };
        
        //  Defines the type of permission.
        blobSasBuilder.SetPermissions(BlobSasPermissions.Read);

        //  Builds an instance of StorageSharedKeyCredential      
        StorageSharedKeyCredential storageSharedKeyCredential = new(_accountName, _key);

        //  Builds the Sas URI.
        return blobSasBuilder.ToSasQueryParameters(storageSharedKeyCredential);
    }

    public Uri CreateBlobUri(string blobName, string containerName) {
        SasQueryParameters parameters = GenerateSaSCredentials(containerName, blobName);
        
        return new UriBuilder {
            Scheme = "https",
            Host = $"{_accountName}.blob.core.windows.net",
            Path = $"files/{containerName}/{blobName}",
            Query = WebUtility.UrlDecode(parameters.ToString())
        }.Uri;
        
    }

You may notice the url decode on parameters.ToString() is because of a similar issue ive seen on stackoverflow where they spoke of double encoding.

However when i return this url to the browser and redirect i get the following error.

This is how i return the URL

 return Ok(_blobUtils.CreateBlobUri(fileName, containerName).ToString());

<Error>
  <Code>AuthenticationFailed</Code>
  <Message>Server failed to authenticate the request. Make sure the value of Authorization header 
  is formed correctly including the signature. RequestId:01696cca-d01e-0023-2ea4-74f5df000000 
  Time:2021-07-09T09:23:33.0250817Z</Message>
  <AuthenticationErrorDetail>Signature fields not well formed.</AuthenticationErrorDetail>
</Error>

If i remove the WebUtility.UrlDecode from the parameters.ToString(), i get this error

<Error>
  <Code>AuthenticationFailed</Code>
  <Message>Server failed to authenticate the request. Make sure the value of Authorization header 
  is formed correctly including the signature. RequestId:016a1821-d01e-0023-3da4-74f5df000000 
  Time:2021-07-09T09:24:38.4051042Z</Message>
  <AuthenticationErrorDetail>Signature did not match. String to sign used was r 2021-07- 
 09T09:14:38Z 2021-07-09T11:24:39Z /blob/${_acountName}/files/bqXbY54sRRsipOUB1PF6/fyI67FYOqDS80y1vNWRL/PRE_OP_CT/0/TK1.left.TST.PTN1.PRE 
 _OP_CT.zip 2020-04-08 b </AuthenticationErrorDetail>
</Error>

The structure of the Blob i am trying to access is:

enter image description here enter image description here enter image description here enter image description here enter image description here And finally the blob we are trying to create a SAS to

enter image description here

Can anyone see why this would fail?

Upvotes: 2

Views: 1025

Answers (1)

Gaurav Mantri
Gaurav Mantri

Reputation: 136346

Please get rid of files from Path here:

return new UriBuilder {
    Scheme = "https",
    Host = $"{_accountName}.blob.core.windows.net",
    Path = $"files/{containerName}/{blobName}",
    Query = WebUtility.UrlDecode(parameters.ToString())
}.Uri;

It should be something like:

return new UriBuilder {
    Scheme = "https",
    Host = $"{_accountName}.blob.core.windows.net",
    Path = $"{containerName}/{blobName}",
    Query = WebUtility.UrlDecode(parameters.ToString())
}.Uri;

UPDATE

Based on the screenshot and the error message, the name of your container is files and the name of the blob is bqXbY54sRRsipOUB1PF6/fyI67FYOqDS80y1vNWRL/PRE_OP_CT/0/TK1.left.TST.PTN1.PRE. Please use them in your code and you should not get the error. You still need to remove files from the Path above as it is already included in your containerName.

The reason your code is failing is because you're calculating SAS token for a blob inside a blob container (the blob path becomes container-name/blob-name). However in your request, you're prepending files to your request URL, your blob path becomes files/container-name/blob-name. Since the SAS token is obtained for a different path but is used for another path, you're getting the error.

Upvotes: 2

Related Questions