2
votes

I would like to give SAS uris to other applications to allow them to send files to a blob container. However the code fails when trying to upload a file giving me an exception which states:

Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.

I'm using aspnetcore and WindowsAzure.Storage version 9.1.0.

        var acc = CloudStorageAccount.Parse("mysecrets");
        CloudBlobClient client = acc.CreateCloudBlobClient();
        var container = client.GetContainerReference("myblobcontainer");
        await container.CreateIfNotExistsAsync();
        var permissions = container.GetPermissionsAsync().Result;
        permissions.SharedAccessPolicies.Add("writepolicy",
            new SharedAccessBlobPolicy
            {
                Permissions =
                    SharedAccessBlobPermissions.Add |
                    SharedAccessBlobPermissions.Create |
                    SharedAccessBlobPermissions.List |
                    SharedAccessBlobPermissions.Write,
            });
        await container.SetPermissionsAsync(permissions);
        var sas = container.GetSharedAccessSignature(null, "writepolicy");
        var accessUri = container.Uri.ToString() + sas;

        var cloudBlobContainer = new CloudBlobContainer(new Uri(accessUri));
        var blob = cloudBlobContainer.GetBlockBlobReference("myfile.txt");
        await blob.UploadFromFileAsync("foo.txt");

I have also tried creating the cloudBlobContainer like this:

var cloudBlobContainer = 
             new CloudBlobContainer(container.Uri, new StorageCredentials(sas));
1

1 Answers

1
votes

Essentially the problem is that your Shared Access Signature (SAS) is missing Expiry Date i.e. date/time when the SAS will expire.

When I ran your code, I got the same error. But when I traced the request/response through Fiddler, this is what Storage Service had sent back:

<?xml version="1.0" encoding="utf-8"?>
  <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:320035be-801e-0040-6e5e-c30407000000
      Time:2018-03-24T10:57:38.7791868Z
    </Message>
    <AuthenticationErrorDetail>
      Signed expiry must be specified in signature or SAS identifier
    </AuthenticationErrorDetail>
  </Error>

What you need to do is add the expiry date/time. You could either add to the shared access policy or specify this when you're creating SAS (but not at both places).

Please use the following code to create SAS:

    var policy = new SharedAccessBlobPolicy()
    {
        SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(15)
    };
    var sas = container.GetSharedAccessSignature(policy, "writepolicy");