Search code examples
azure-blob-storageazure-python-sdkshared-access-signatures

Why does generate_blob_sas() fail but generate_container_sas() works fine with the same values?


I'm stumped. I'm attempting to use generate_blob_sas() function, but for some reason, the SAS token is malformed. I'm able to use the generate_container_sas() function with the same account, account key and container names. Seems to be the addition of the stg_blob name(?).

Thoughts?

Example:

import os

from azure.storage.blob import generate_blob_sas, BlobSasPermissions
from datetime import datetime, timedelta
import urllib.parse


def generate_sas_token(stg_account:str, 
                       stg_container:str, 
                       stg_blob:str, 
                       stg_account_key:str,
                       token_perms:str,
                       token_duration:int) -> str:

        blob_sas_token = generate_blob_sas(
                account_name = stg_account,
                container_name = stg_container,
                blob_name = stg_blob,
                account_key = stg_account_key,
                permission = BlobSasPermissions.from_string(token_perms),
                expiry = datetime.utcnow() + timedelta(minutes=token_duration)
            )
        return blob_sas_token


stg_account = 'myaccount'
stg_container = 'mycontainer'
stg_blob = '/folder1/folder2/blob.jpg'
stg_account_key = 'yeah'
token_perms = 'r'
token_duration = 10

The function executes successfully, but when the blob url + blob_sas_token are put into a browser, it results in the error below:

https://myaccount.blob.core.windows.net/mycontainer/folder1/folder2/blob-name.jpg?se=2023-04-17T22%3A37%3A45Z&sp=r&sv=2021-12-02&sr=b&sig=<redacted>

<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:<longGUID> Time:2023-04-17T22:28:49.8347629Z</Message>
  <AuthenticationErrorDetail>
    Signature did not match. String to sign used was r 2023-04-17T22:37:45Z /blob/<account-name>/<container-name>/<folder1>/<folder2>/<blob-name>.jpg 2021-12-02 b 
  </AuthenticationErrorDetail>
</Error>

Solution

  • I tried in my environment and got the below results: 

    Initially, I tried with the same code and got the same error in my environment.

        <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:ee478ce7-601e-003c-61aa-71c892000000 Time:2023-04-18T04:03:05.1834825Z</Message>
    <AuthenticationErrorDetail>Signature did not match. String to sign used was r 2023-04-18T04:12:18Z /blob/venkat123/test/folder1/folder2/image1.png 2021-12-02 b </AuthenticationErrorDetail>
    </Error> 
    

    enter image description here 

    I agree with Gaurav Mantri, you need to change the  stg_blob = '/folder1/folder2/blob.jpg to stg_blob='folder1/folder2/blob.jpg

    Here is a workaround to get the SAS token with blob url using Python.

    Code:

     import os    
     from azure.storage.blob import generate_blob_sas, BlobSasPermissions
     from datetime import datetime, timedelta
     import urllib.parse   
    
     def generate_sas_token():
                stg_account = 'venkat123'
                stg_container = 'test'
                stg_blob = 'folder1/folder2/image1.png'
                stg_account_key = 'Your account key'
                token_perms = 'r'
                token_duration = 10
    
                blob_sas_token = generate_blob_sas(
                        account_name = stg_account,
                        container_name = stg_container,
                        blob_name = stg_blob,
                        account_key = stg_account_key,
                        permission = BlobSasPermissions.from_string(token_perms),
                        expiry = datetime.utcnow() + timedelta(minutes=token_duration)
                )
                blob_url_with_sas = f"https://{stg_account}.blob.core.windows.net/{stg_container}/{stg_blob}?{blob_sas_token}"
                print(blob_url_with_sas)
        generate_sas_token()
    

    Output:

    enter image description here

    Browser:

    The function executes successfully, but when the blob URL + blob_sas_token is put into a browser, I can able to see the image clearly.

    enter image description here