Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate the Azure Table Service SAS token from c# code?

I would like to generate the SAS token for Azure table service from C# code. I generated the one from the portal which looks like

?sv=2016-05-31&ss=t&srt=sco&sp=rwdlacu&se=2017-03-23T20:05:14Z&st=2017-03-23T12:05:14Z&sip={MY_IP}&spr=https&sig=fL9GNAZqybSlQKWvaspwr%2FrFFtWO%2F5jVgFu1Ayu94Ic%3D

How to generate such kind of token from c# code? If there is any tutorial please redirect me to it. I tried with a method below, but the token generated is invalid.

UPDATED CODE

I am still getting an error 403 Forbidden. Is my code to compute the signature correct?

var StringToSign = "{Storage_account_name}" + "\n" +
                            "rwdlacu" + "\n" +
                            "t" + "\n" +
                            "sco" + "\n" +
                            "2017-03-24T12:05:14Z" + "\n" +
                            "2017-03-24T20:05:14Z" + "\n" +
                            "{IP}" + "\n" +
                            "https" + "\n" +
                            "2016-05-31" + "\n";
string encodedString = HttpUtility.UrlEncode(StringToSign);
HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String("accountkey"));
var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(encodedString)));
like image 598
tRuEsAtM Avatar asked Mar 23 '17 19:03

tRuEsAtM


People also ask

How do I get Azure storage SAS token?

The most straightforward way to generate a SAS token is using the Azure Portal. By using the Azure portal, you can navigate the various options graphically. To create a token via the Azure portal, first, navigate to the storage account you'd like to access under the Settings section then click Shared access signature.


1 Answers

The reason you're running into the issue is because you're calculating signature for SAS based on the logic for calculating Authorization header. StringToSign is different in both cases.

For SAS, this should be (for Service SAS):

StringToSign = signedpermissions + "\n" +  
               signedstart + "\n" +  
               signedexpiry + "\n" +  
               canonicalizedresource + "\n" +  
               signedidentifier + "\n" +  
               signedIP + "\n" +  
               signedProtocol + "\n" +  
               signedversion + "\n" +  
               startingPartitionKey + "\n"  
               startingRowKey + "\n"  
               endingPartitionKey + "\n"  
               endingRowKey  

If you want to use Account SAS (which is what Portal does), it should be:

StringToSign = accountname + "\n" +  
    signedpermissions + "\n" +  
    signedservice + "\n" +  
    signedresourcetype + "\n" +  
    signedstart + "\n" +  
    signedexpiry + "\n" +  
    signedIP + "\n" +  
    signedProtocol + "\n" +  
    signedversion + "\n"  

So based on your parameters, the StringToSign for Account SAS would be:

StringToSign = {youraccountname} + "\n" +  
    "rwdlacu" + "\n" +  
    "t" + "\n" +  
    "sco" + "\n" +  
    "2017-03-23T12:05:14Z" + "\n" +  
    "2017-03-23T20:05:14Z" + "\n" +  
    {yourip} + "\n" +  
    "https" + "\n" +  
    "2016-05-31 + "\n"  

The computation for signature is correct.

You may find these links helpful to learn more about computing SAS: Account SAS and Service SAS.

UPDATE

There's an issue with hmac calculation as well. It should be using your account key and also it should use Convert.FromBase64String.

HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String(accountKey));

Also, you should not URLEncode StringToSign. Elements there should be URL decoded.

Lastly the SAS token should look like what you're getting back from the portal.

Code Sample

    static void AccountSasSample()
    {
        var accountName = "your-account-name";
        var accountKey = "your-account-key";
        var start = DateTime.UtcNow.AddHours(-1).ToString("yyyy-MM-ddTHH:mm:ssZ");
        var end = DateTime.UtcNow.AddHours(1).ToString("yyyy-MM-ddTHH:mm:ssZ");
        var permission = "rwdlacu";
        var serviceType = "t";
        var resourceTypes = "sco";
        var ipAddress = "your-ip-address";
        var protocol = "https";
        var serviceVersion = "2016-05-31";
        var stringToSign = string.Format("{0}\n{1}\n{2}\n{3}\n{4}\n{5}\n{6}\n{7}\n{8}\n", accountName, permission, serviceType, resourceTypes, start, end, ipAddress, protocol, serviceVersion);
        Console.WriteLine(stringToSign);
        HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String(accountKey));
        string signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
        var sasToken = string.Format("?sv={0}&ss={1}&srt={2}&sp={3}&se={4}&st={5}&sip={6}&spr={7}&sig={8}", serviceVersion,
            serviceType, resourceTypes, permission, end, start, ipAddress, protocol, HttpUtility.UrlEncode(signature));
        Console.WriteLine(sasToken);
        var urlToListTables = string.Format("https://{0}.table.core.windows.net/Tables{1}", accountName, sasToken);
        //Copy this urlToListTables & paste it in browser's address bar. You should be able to see the list of tables in your storage account.
    }
like image 175
Gaurav Mantri Avatar answered Nov 10 '22 15:11

Gaurav Mantri