Search code examples
azuresalesforceazure-storageapex

Creating Azure File Storage SAS in Salesforce does not work


I am trying to create a Shared Access Signature (SAS) for the Azure File Storage in Salesforce Apex but not getting anywhere. Here is my code:

String link = 'https://<accountName>.file.core.windows.net/<folderName>/test.txt';
String key = '...' // key of the account

String spe = 'r'; //read
String st = '2018-06-07T08:49:00Z';
String se = '2018-06-09T08:49:00Z';
String res = '/file/<accountName>/<folderName>/test.txt';
String sv = '2017-11-09';
String sr = 'f'; // file
String spr = 'https';

String sts = spe + '\n'  +
    st + '\n' +
    se + '\n' +
    res + '\n' +
    spr + '\n'+
    sv + '\n';  

Blob data = crypto.generateMac('HmacSHA256', Blob.valueOf(sts), Blob.valueOf(key));
String sas = EncodingUtil.base64Encode(data);
sas = EncodingUtil.urlEncode(sas, 'UTF-8');
link += '?sv=' + sv + '&st=' + st + '&se=' + se + '&sr=' + sr + '&sp=' + spe 
               + '&spr=' + spr + '&sig=' + sas;
System.debug(link);

When I copy paste the link in the browser, the response is:

<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:... Time:2018-06-07T21:56:01.7374549Z
  </Message>
  <AuthenticationErrorDetail>
    Signature did not match. String to sign used was r 2018-06-07T08:49:00Z 2018-06-09T08:49:00Z /file/<accountName>/<folderName>/test.txt https 2017-11-09
  </AuthenticationErrorDetail>
</Error>

What am I doing wrong here?


Solution

  • As mentioned by @superfell in the comments, the issue is with the following line of code:

    Blob data = crypto.generateMac('HmacSHA256', Blob.valueOf(sts), Blob.valueOf(key));
    

    Please change this line of code to:

    Blob data = crypto.generateMac('HmacSHA256', Blob.valueOf(sts), EncodingUtil.base64Decode(key));
    

    and you should not get this error. Essentially the key is a base64 encoded string and you need to use proper decoding method to get a byte array.