Reputation: 2856
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));
Upvotes: 2
Views: 568
Reputation: 136146
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");
Upvotes: 1