Question

I'm having trouble getting shared access signatures to work with Storage 2.0..

I use the code:

if (blob.Exists())
{
    var expires = DateTime.UtcNow.AddMinutes(30);
    var sas = blob.GetSharedAccessSignature(new Microsoft.WindowsAzure.Storage.Blob.SharedAccessBlobPolicy
    {
        Permissions = Microsoft.WindowsAzure.Storage.Blob.SharedAccessBlobPermissions.Read,
        SharedAccessExpiryTime = expires
    });
    url = string.Concat(blob.Uri.AbsoluteUri, sas);
}
return url;

But if I debug the session and paste the URL into a browser, I get an 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:c1a1dd2b-bf4a-4a6b-bab2-ab1cb9363d27 Time:2012-11-19T14:41:51.1254531Z
  </Message>
  <AuthenticationErrorDetail>
Signature did not match. String to sign used was r 2012-11-19T15:11:36Z /container/path/1356/pic.jpg 2012-02-12
  </AuthenticationErrorDetail>
</Error>

Can anybody help?

UPDATE: A resulting URL looks like: https://storageaccountname.blob.core.windows.net/container/path/1356/pic.jpg?sv=2012-02-12&se=2012-11-19T19%3A25%3A32Z&sr=b&sp=r&sig=s6QIdwAGY4xC8fs4L9pK8hAGIY%2F8x58aqBcFbejYPdM%3D

Was it helpful?

Solution

I am getting the same error. This code used to work before I updated to 2.0:

var sharedAccessPolicy = new SharedAccessBlobPolicy
{
  SharedAccessStartTime = DateTime.UtcNow.AddMinutes(-10),
  SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(30),
  Permissions = SharedAccessBlobPermissions.Read
};
var sharedAccessSignature = _blockblob.GetSharedAccessSignature(sharedAccessPolicy);
return _blockblob.Uri.AbsoluteUri + sharedAccessSignature;

I get the uri:

http://127.0.0.1:10000/devstoreaccount1/original/c04d2a1c-980b-42c5-b76e-b71185f027b6.jpg?sv=2012-02-12&st=2012-11-20T08%3A30%3A24Z&se=2012-11-20T09%3A10%3A24Z&sr=b&sp=r&sig=9%2BVg6mSGqyrfr5rPlNJ6GSv%2BHN3J9k%2FWFRLYmx3xCvQ%3D

UPDATE, SOLVED:

In my code above I have _blockBlob. This was set in the constuctor with

var blobClient = account.CreateCloudBlobClient();
var container = blobClient.GetContainerReference(containerName);
CloudBlockBlob _blockblob = container.GetBlockBlobReference(fileName);

Changing the last line(as suggested by clausndk) to

ICloudBlob _test = container.GetBlobReferenceFromServer(fileName);

solves the problem since the call to GetSharedAccessSignature on _test results in a different (valid) signature.

Looking at the source code for Azure storage and using the debugger on my application I have found the cause of the problem. In my code I have containerName with a trailing slash (original/). This is not a problem except when it comes to GetSharedAccessSignature. Here the extra slash messes up the canonicalName (one slash is added in the code giving double slashes) and this invalidates the signature. The reason GetBlobReferenceFromServer works is that it asks the servers (via REST API) for the blob and the resulting CloudBlockBlob has the slash removed.

In my code I have removed the trailing slash but Sandrino Di Mattia's solution to use .Trim('/') on the container name also works. I think this is preferred over using GetBlobReferenceFromServer as it would cause an extra server call.

Hopefully the implementation of GetCanonicalName in CloudBlockBlobBase will be changed to handle trailing slashes in the future (I have created an issue on GitHub for this) but for now this "workaround" works.

OTHER TIPS

Could you try the following code?

var pathToMyBlob = "/path/1356/pic.jpg";
var blob = container.GetBlockBlobReference(pathToMyBlob.TrimStart('/'));

var expires = DateTime.UtcNow.AddMinutes(30);
var sas = blob.GetSharedAccessSignature(new Microsoft.WindowsAzure.Storage.Blob.SharedAccessBlobPolicy
{
    Permissions = Microsoft.WindowsAzure.Storage.Blob.SharedAccessBlobPermissions.Read,
    SharedAccessExpiryTime = expires
});

Look at the second line, especially the call to TrimStart. I was able to reproduce the issue when trying to get a blob reference of a file where the path started with a slash. By removing the slash the problem was fixed. So:

  • /path/1356/pic.jpg > Does not work
  • path/1356/pic.jpg > Works
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top