Azure storage blob string to sign issue

Anonymous
2022-09-15T17:15:04.873+00:00

I am using Laravel and I am having an issue with the authentication to allow me to download a document from azure storage.
The error I receive 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:d314bd7e-b01e-002a-0623-c9324e000000 Time:2022-09-15T16:49:08.5148234Z</Message>
<AuthenticationErrorDetail>Signature did not match. String to sign used was r 2022-09-16T16:49:02Z /blob/tsiattachments/tsi-fnb/tsi/Prod/Orders/325986/Communication/Cargo Dues.pdf https 2020-12-06 b </AuthenticationErrorDetail>
</Error>

The code I am using comes from two functions.
First function:
/**
* Function to generate Shared Access Signature for a blob
*
* @Paramjeet Dahiya string $accountName The account name
* @Paramjeet Dahiya string $container The container name
* @Paramjeet Dahiya string $blob The blob / file name
* @Paramjeet Dahiya string $resourceType The resource type, default = b for blob
* @Paramjeet Dahiya string $permissions The permissions, e.g. r for read
* @Paramjeet Dahiya string $expiry The expiry date
* @Paramjeet Dahiya string $key The key
*
* @return string The generated signature
*/
public static function generateSasForBlob($accountName,$container, $blob, $resourceType, $permissions, $expiry, $key) {

    $stringToSign = $permissions . "\n" .  
        "" . "\n" .  
        $expiry . "\n" .  
        '/' . $accountName . '/' . $container . $blob . "\n" .  
        "" . "\n" .  
        "" . "\n" .  
        "https" . "\n" .  
        "2020-12-06" . "\n" .  
        "b\n"."\n"."\n"."\n"."\n"."\n";  

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

second function that calls the first is

/**  
 * Function to generate a blob url with a secure signature (i.e. pre-signed URL)  
 *  
 * @param string $blob          The blob / file name  
 * @param string $resourceType  The resource type, default = b for blob  
 * @param string $permissions   The permissions, e.g. r for read  
 * @param string $expiry        The expiry date  
 *  
 * @return string The generated URL  
 */  
// public static function generateBlobUrl($blob, $resourceType='b', $permissions='r', $expiry = null)  
public static function generateBlobUrl($blob, $resourceType='b', $permissions='r', $expiry = null) {  

    $resourceType='b';  
    $permissions='r';  
    $expiry = null;  

    $accountName = 'tsiattachments';  
    $container = 'tsi-fnb';  
    $key = 'XXXXXXXXXXXXXXXXXXXXXX==';  

    if($expiry == null) {  
        $expiry = gmdate("Y-m-d\TH:i:s\Z", time() + 60*60*24); // default 24 hours  
    }  

    $signature = self::generateSasForBlob($accountName, $container, $blob, $resourceType, $permissions, $expiry, $key);  
    /* Create the signed query part */  
    $parts = array();  
    $parts[] = 'sv=2020-12-06';  
    $parts[] = (!empty($expiry))? 'se=' . urlencode($expiry):'';  
    $parts[] = 'sr=' . $resourceType;  
    $parts[] = (!empty($permissions))? 'sp='. $permissions:'';  
    $parts[] = 'spr=https';  
    $parts[] = 'sig=' . urlencode($signature);  

    /* Create the signed blob URL */  
    $_url = 'https://tsiattachments.blob.core.windows.net/'  
        . $container . '/tsi/'  
        // replace below code with the correct path in variables.  
        . str_replace('/tsi/Staging/', 'Prod/', $blob)  
        . '?'  
        . implode('&', $parts);  

    return $_url;  
}  

However I am getting an error but not certain as to why.
Could someone assist please.

Note that the headers are sent in the ApiHelper contructed that uses a getRequest function which deals with the button and variables associated with the user that wishes to download the document.

I am not sure what I am missing and I have read through the documentation on this.

Azure Blob Storage
Azure Blob Storage
An Azure service that stores unstructured data in the cloud as blobs.
2,790 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Anonymous
    2022-09-21T06:22:22.467+00:00

    I solved the error. I was getting the wrong extension to my staging env in the blob. So I used a str_replace on both blob variables in the generate sas and generate url. This solved the issue.

    1 person found this answer helpful.
    0 comments No comments

  2. shiva patpi 13,251 Reputation points Microsoft Employee
    2022-09-15T20:41:53.157+00:00

    Hello @Anonymous ,
    As per the error message, it means the application (or the user under which the code is being executed) don't have access to the storage account by the SAS URI which is being generated.
    Couple of things for suggestion and validate:

    1) Kindly check for the storage account if there is any firewall enabled. If yes - try to test it out by selecting "Allow access from All Networks" (You can find this setting on Azure Portal -> Storage Account -> Networking)

    2) Common API error codes: https://learn.microsoft.com/en-us/rest/api/storageservices/common-rest-api-error-codes
    3) In the generateSasForBlob , I am seeing lot of special characters (\n, \b" etc - try removing those
    4) Line20 , generateBlobUrl function , Try using secondary key of the storage account
    5) Mainly you will have to look at the variable $stringToSign value which is being generated using different parameters
    5.1) Definitely the requests is failing with signature mismatch , Try to debug by checking the value assigned to $stringToSign
    6) Line No: 23 in GenerateBlobURI function , please validate the expiryDate - make sure this value is at least +6hrs

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.