1
votes

I'm trying to upload using a SAS key directly from a browser, since files that will be uploaded may be very big (500MB-1GB+) and I don't want them to go through our backend hosted on Azure.

I'm following this great post here but I run into CORS issue on the on hand and a 403 error on the other.

The CORS error

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:36923' is therefore not allowed access. The response had HTTP status code 403.

As you can see I'm trying to get my ASP MVC app running locally to upload to Azure for testing purposes.

And the 403 error received:

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

The way I generated my SAS URI (which expires next year and has Write access) is the following:

// First I create the blob container
public static CloudBlockBlob CreateBlobContainer(string strContainer)
{
    CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["StorageConnectionString"].ToString());

    CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

    CloudBlobContainer container = blobClient.GetContainerReference(strContainer);

    container.CreateIfNotExists();

    CloudBlockBlob blockBlob = new CloudBlockBlob(container.Uri, new StorageCredentials(ConfigurationManager.AppSettings["AccountName"], ConfigurationManager.AppSettings["AccountKey"]));

    return blockBlob;
}

//Then I create a SAS key for that container
public static string GetSaSForBlobContainer(CloudBlockBlob blob, SharedAccessBlobPermissions permission)


    var sas = blob.GetSharedAccessSignature(new SharedAccessBlobPolicy()
    {
        Permissions = permission,
        SharedAccessStartTime = DateTime.UtcNow.AddMinutes(-5),
        SharedAccessExpiryTime = DateTime.UtcNow.AddYears(1),
    });

    return string.Format(CultureInfo.InvariantCulture, "{0}{1}", blob.Uri, sas);
}

//Above methods invoked as such
container = FileManager.CreateBlobContainer("supercontainer");
var sasUri = FileManager.GetSaSForBlobContainer(container, SharedAccessBlobPermissions.Write);

So I create a container then generate a URI that allows uploading to it for a year or so.

The sasUri above ends up being exposed in an ASP MVC view, accessible to javascript logic. It it the baseUrl of the above quoted blog post.

Here's the CORS setting on my container:

CORS

Why would I get this CORS error ? Also, why the error about Authorization header?

I thought the idea of using a SAS URI was to not have to expose an account name/key to the client.

Am I missing something ?

1
Same guy from that blog post :). Are you creating SAS on the blob container or the blob? From your code, it seems you're doing it on the blob and not the container. Is there some more code that you did not include in the question? If so, then please include that in the question.Gaurav Mantri
@GauravMantri I edited the part where I show how I call both C# methods. I would think I'm doing the SAS generation at container level, maybe my eyes are fooling me...Francis Ducharme
Thanks! I believe the problem is that you're creating a block blob with container's URI as name. So your blob's name is https://youraccount.blob.core.windows.net/supercontainer. Here's what I would suggest: Please have CreateBlobContainer return container object instead of blob and create a SAS on that i.e. 1st parameter for GetSaSForBlobContainer would be of type CloudBlobContainer instead of CloudBlockBlob. Do give it a try.Gaurav Mantri
@GauravMantri That was it! Thanks, post it as answer and I will accept it.Francis Ducharme

1 Answers

3
votes

The blog post you linked assumes the shared access signature to be created on blob container and not blob because you don't really know the name of the file user is going to upload beforehand. However in your code you're creating the SAS on blob instead of blob container and this is why you're getting 403 error.

To fix this, please change your CreateBlobContainer method and have it return an object of type CloudBlobContainer instead of CloudBlockBlob. Then, please update your GetSaSForBlobContainer and have its 1st parameter of type CloudBlobContainer instead of CloudBlockBlob. Once you make these changes, you should not get the 403 error you're getting.