2
votes

I'm trying to create a SAS for my azure blob storage, but i'm getting the message that my signature fields are not well formed.

First a function that creates the signature:

function getSASForBlob($accountName,$container, $blob, $resourceType, $permissions, $expiry,$key){

    /* Create the signature */
    $_arraysign = array();
    $_arraysign[] = $permissions;
    $_arraysign[] = '';
    $_arraysign[] = $expiry;
    $_arraysign[] = '/' . $accountName . '/' . $container . '/' . $blob;
    $_arraysign[] = '';
    $_arraysign[] = "2014-02-14"; //the API version is now required
    $_arraysign[] = '';
    $_arraysign[] = '';
    $_arraysign[] = '';
    $_arraysign[] = '';
    $_arraysign[] = '';

    $_str2sign = implode("\n", $_arraysign);    

    return base64_encode(
    hash_hmac('sha256', urldecode(utf8_encode($_str2sign)), base64_decode($key), true)
    );
}

Then a function that provides me the URL:

function getBlobUrl($accountName,$container,$blob,$resourceType,$permissions,$expiry,$_signature){
    /* Create the signed query part */
    $_parts = array();
    $_parts[] = (!empty($expiry))?'se=' . urlencode($expiry):'';
    $_parts[] = 'sr=' . $resourceType;
    $_parts[] = (!empty($permissions))?'sp=' . $permissions:'';
    $_parts[] = 'sig=' . urlencode($_signature);
    $_parts[] = 'sv=2014-02-14';

    /* Create the signed blob URL */
    $_url = 'https://'
    .$accountName.'.blob.core.windows.net/'
    . $container . '/'
    . $blob . '?'
    . implode('&', $_parts);

    return $_url;
}

Then I call the functions and specify the parameters.

$container = '87d57f73-a327-4344-91a4-27848d319a66';
$blob = '8C6CBCEB-F962-4939-AD9B-818C124AD3D9.mp4';
$endDate = date('YYYY-MM-DDThh:mmTZD', strtotime('+1 day'));

$_signature = getSASForBlob($accountName,$container,$blob,'b','r',$endDate,$accountKey);
$_blobUrl = getBlobUrl($accountName,$container,$blob,'b','r',$endDate,$_signature);

https://ttresources.blob.core.windows.net/87d57f73-a327-4344-91a4-27848d319a66/8C6CBCEB-F962-4939-AD9B-818C124AD3D9.mp4?se=2016201620162016-FebFeb-ThuThuCET1111%3A0202CET3600Thu&sr=b&sp=r&sig=1VdOjLX179wLQv5o265JBR%2B6CaLTr1nwCs6GHSVqfbA%3D&sv=2014-02-14

This is the url I get as my result, when I follow it I'm getting the next error message:

AuthenticationFailed Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. RequestId:41f089a3-0001-0027-376f-6966d1000000 Time:2016-02-17T10:38:00.2724783Z Signature fields not well formed.

2

2 Answers

1
votes

As the issue is that you have made the wrong datetime format. According the guide:

The signedstart and signedexpiry fields must be expressed as UTC times and must adhere to a valid ISO 8601 format. Supported ISO 8601 formats include the following:

  • YYYY-MM-DD
  • YYYY-MM-DDThh:mmTZD
  • YYYY-MM-DDThh:mm:ssTZD

And in PHP, you should create the datetime in the following format:

$expiry = date('Y-m-d\TH:i:s\Z', strtotime('+1 day'));

Then it will be the correct format.

0
votes

There's a problem in the way you're constructing canonicalizedresource. Please remove / before $accountName from this line:

$_arraysign[] = '/' . $accountName . '/' . $container . '/' . $blob;

So it should be:

$_arraysign[] = $accountName . '/' . $container . '/' . $blob;

Based on the documentation here:

URL = https://myaccount.blob.core.windows.net/music/intro.mp3 
canonicalizedresource = "myaccount/music/intro.mp3"