How to create an Azure Storage SAS token to allow upload of file from browser using @azure/storage-blob

Paul Rony 20 Reputation points
2025-03-13T16:47:05.03+00:00

I believe that I'm very close to having the upload working as a manually generated SAS token from the portal site works in the browser to load a file. But, I need to be able to create a blob specific token for anonymous user upload to that specific name and for a 1 hour period.

The following code generates a SAS token without any errors, but the client returns "Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature."

		BlobServiceClient client = new BlobServiceClient(AzureStorageConnectionString());

		BlobContainerClient containerClient = client.GetBlobContainerClient("videos");

		BlobClient blobClient = containerClient.GetBlobClient(sUserID + "/" + model.name);

		BlobSasBuilder sasBuilder = new BlobSasBuilder()

		{

			BlobContainerName = containerClient.Name,

			BlobName          = blobClient.Name,

			Resource          = "b",

			StartsOn          = DateTimeOffset.UtcNow,

			ExpiresOn         = DateTimeOffset.UtcNow.AddHours(1)

		};

		sasBuilder.SetPermissions(BlobContainerSasPermissions.Create);

		var sasToken = sasBuilder.ToSasQueryParameters(new Azure.Storage.StorageSharedKeyCredential(AzureStorageAccountName(), AzureStorageSubscriptionKey()));

		Uri sasURI = blobClient.GenerateSasUri(sasBuilder);

		string sSasToken = sasURI.ToString();
```As I mentioned above, the client code works with a manually generated SAS token, so I expect it to work with a blob-specific SAS token.  Here is the client side:

```typescript
			this.blobServiceClient = new BlobServiceClient(sasToken);

			const containerClient = this.blobServiceClient.getContainerClient(containerName);

			const blockBlobClient = containerClient.getBlockBlobClient(blobName);

			const opts: BlockBlobParallelUploadOptions =

			{

				blockSize: 4 * 1024 * 1024, // 4MB blocks

				onProgress: (progress: TransferProgressEvent) =>

				{

					this.handleProgress(progress.loadedBytes);

					console.log("uploadData progress", progress);

				},

				abortSignal: this.abortSignal

			}

			const uploadBlobResponse: BlobUploadCommonResponse = await blockBlobClient.uploadData(this.file, opts);

			console.log("uploadBlobResponse", uploadBlobResponse);
```Yes, the container name and blob name are the same on server SAS token generation and client upload request.

Azure Storage
Azure Storage
Globally unique resources that provide access to data management services and serve as the parent namespace for the services.
3,539 questions
0 comments No comments
{count} votes

Accepted answer
  1. Vinodh247 34,741 Reputation points MVP Volunteer Moderator
    2025-03-14T03:52:31.32+00:00

    Hi ,

    Thanks for reaching out to Microsoft Q&A.

    Your SAS token generation code appears close, but the authentication issue is likely due to incorrect permissions, missing signature, or an issue with how the SAS token is applied. Here are some steps to fix it:

    1. Fixing the SAS Token Generation:
    • You need to explicitly call .SetPermissions() with read, write, and create permissions for upload operations.
    • Make sure the ToSasQueryParameters() method is correctly generating the SAS token.

    Try this updated code:

    BlobServiceClient client = new BlobServiceClient(AzureStorageConnectionString());
    BlobContainerClient containerClient = client.GetBlobContainerClient("videos");
    BlobClient blobClient = containerClient.GetBlobClient(sUserID + "/" + model.name);
    
    BlobSasBuilder sasBuilder = new BlobSasBuilder()
    {
        BlobContainerName = containerClient.Name,
        BlobName          = blobClient.Name,
        Resource          = "b",  // "b" for Blob-level SAS
        StartsOn          = DateTimeOffset.UtcNow,
        ExpiresOn         = DateTimeOffset.UtcNow.AddHours(1)
    };
    
    // Correcting permissions - allowing write and create
    sasBuilder.SetPermissions(BlobSasPermissions.Write | BlobSasPermissions.Create);
    
    var sasToken = sasBuilder.ToSasQueryParameters(
        new StorageSharedKeyCredential(AzureStorageAccountName(), AzureStorageSubscriptionKey()))
        .ToString();
    
    // Generate a full SAS URI
    Uri sasURI = new Uri($"{blobClient.Uri}?{sasToken}");
    
    // Use this full SAS URI for the client-side upload
    string sSasToken = sasURI.ToString();
    
    1. Fixing client Side Code (TypeScript)

    Ensure you're correctly using the SAS token to initialize the BlobServiceClient:

    // Use the correct SAS token URI, not just the token itself
    this.blobServiceClient = new BlobServiceClient(sSasToken);
    const containerClient = this.blobServiceClient.getContainerClient(containerName);
    const blockBlobClient = containerClient.getBlockBlobClient(blobName);
    const opts: BlockBlobParallelUploadOptions = {
        blockSize: 4 * 1024 * 1024, // 4MB blocks
        onProgress: (progress: TransferProgressEvent) => {
            this.handleProgress(progress.loadedBytes);
            console.log("uploadData progress", progress);
        },
        abortSignal: this.abortSignal
    };
    // Uploading the file
    const uploadBlobResponse: BlobUploadCommonResponse = await blockBlobClient.uploadData(this.file, opts);
    console.log("uploadBlobResponse", uploadBlobResponse);
    
    
    • Ensure your Storage Account Key is Correct
    • Check if your SAS Token has a Signature (sig= in the URL)
    • Ensure the blob exists and container access allows SAS-based writes
    • Permissions should include Write and Create
    • Use the full SAS URI in the client code (https://storageaccount.blob.core.windows.net/container/blob?SAS), not just the token

    Please feel free to click the 'Upvote' (Thumbs-up) button and 'Accept as Answer'. This helps the community by allowing others with similar queries to easily find the solution.

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

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.