Introduction
Azure Blob Storage is a cloud storage service that allows you to store and access large amounts of unstructured data, such as images, videos, and documents. One of the key features of Azure Blob Storage is the ability to generate Shared Access Signatures (SAS) that provide time-limited access to your blobs, without requiring your clients to have access to your storage account key.
In this blog post, we’ll explore how to generate SAS tokens for Azure Blob Storage containers in C# and return URLs to download blobs, without exposing your storage account key.
Demo
Prerequisites
Before we dive into the code, make sure you have the following:
- An Azure Blob Storage account with a container that contains some blobs.
- A C# development environment, such as Visual Studio or Visual Studio Code.
When do we need SAS tokens?
If your Azure Blob Storage container is private, you will need to generate a Shared Access Signature (SAS) for the blob that the user wants to download. The SAS is a token that grants time-limited access to the blob, without requiring the user to be authenticated with Azure AD.
Here are the high-level steps to implement this in your scenario:
- Generate the SAS token in your server-side code. You can use the
CloudBlob.GetSharedAccessSignature
method to generate the SAS token for the blob. - Create a URL to the blob that includes the SAS token. The URL should be in the format:
https://<accountname>.blob.core.windows.net/<containername>/<blobname><SAS token>
. You can construct the URL by concatenating the various parts together. - Return the URL to the client-side code, where it can be used as the
href
attribute of an<a>
tag. When the user clicks the link, their browser will download the file directly from Azure Blob Storage.
Generating SAS Tokens for Azure Blob Storage in C#
To generate a SAS token for a blob in Azure Blob Storage, you need to provide the following parameters:
- The name of the container that contains the blob.
- The name of the blob.
- The permissions that you want to grant to the client, such as read, write, or delete.
- The expiry time for the SAS token.
Here’s the C# code to generate a SAS token for a blob:
using Microsoft.Azure.Storage;
using Microsoft.Azure.Storage.Blob;
using System;
public string GetBlobSasUri(string containerName, string blobName, string permissions, DateTime expiryTime)
{
var storageAccount = CloudStorageAccount.Parse("YourStorageConnectionString");
var blobClient = storageAccount.CreateCloudBlobClient();
var container = blobClient.GetContainerReference(containerName);
var blob = container.GetBlockBlobReference(blobName);
var sasConstraints = new SharedAccessBlobPolicy
{
SharedAccessStartTime = DateTime.UtcNow.AddMinutes(-5),
SharedAccessExpiryTime = expiryTime,
Permissions = SharedAccessBlobPermissions.Create | SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.Read
};
var sasToken = blob.GetSharedAccessSignature(sasConstraints);
var blobUri = blob.Uri.AbsoluteUri;
return $"{blobUri}{sasToken}";
}
This code uses the Microsoft.Azure.Storage
and Microsoft.Azure.Storage.Blob
namespaces to create a CloudBlobClient
and get a reference to the container and blob that you want to generate a SAS token for. You can then create a SharedAccessBlobPolicy
object and set its SharedAccessExpiryTime
property to specify the expiry time for the SAS token.
Finally, you can call the GetSharedAccessSignature
method on the blob to generate a SAS token for it, and append the SAS token to the blob URI to create a complete download URL.
Returning URLs to Download Blobs
Now that we know how to generate SAS tokens for blobs in Azure Blob Storage, let’s look at how to return URLs to download blobs to clients.
Here’s the C# code to get a list of blobs in a container and return their download URLs with SAS tokens:
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace YourNamespace
{
[ApiController]
[Route("[controller]")]
public class BlobController : ControllerBase
{
private readonly IConfiguration _config;
public BlobController(IConfiguration config)
{
_config = config;
}
[HttpGet("{containerName}")]
public async Task<IActionResult> GetBlobs(string containerName)
{
try
{
var containerClient = new BlobContainerClient(_config.GetConnectionString("AzureWebJobsStorage"), containerName);
var blobs = new List<string>();
await foreach (BlobItem blobItem in containerClient.GetBlobsAsync())
{
var blobClient = containerClient.GetBlobClient(blobItem.Name);
var sasBuilder = new BlobSasBuilder
{
BlobContainerName = containerName,
BlobName = blobItem.Name,
Resource = "b",
StartsOn = DateTime.UtcNow.AddMinutes(-5),
ExpiresOn = DateTime.UtcNow.AddHours(1),
Protocol = SasProtocol.Https,
IpRange = new SasIpRange(System.Net.IPAddress.None, System.Net.IPAddress.None)
};
sasBuilder.SetPermissions(BlobSasPermissions.Read);
var sasToken = sasBuilder.ToSasQueryParameters(_config.GetSection("AzureBlobStorage:AccountKey").Value).ToString();
var blobUrl = $"{blobClient.Uri}?{sasToken}";
blobs.Add(blobUrl);
}
return Ok(blobs);
}
catch (Exception ex)
{
// Handle exceptions here
return StatusCode(StatusCodes.Status500InternalServerError, ex.Message);
}
}
}
}
Let’s go through this code step by step:
- We start by injecting the
IConfiguration
interface into our controller. This will allow us to read the connection string and account key from ourappsettings.json
file. - We define a GET endpoint that takes the container name as a parameter.
- We create a new instance of the
BlobContainerClient
class, passing in the connection string and the container name. - We create an empty list of strings to hold the blob URLs with SAS tokens.
- We use a
foreach
loop to iterate through each blob in the container. - For each blob, we get a reference to its
BlobClient
. - We create a new instance of the
BlobSasBuilder
class, which will be used to generate the SAS token. - We set the
BlobContainerName
,BlobName
,Resource
,StartsOn
,ExpiresOn
,Protocol
, andIpRange
properties of theBlobSasBuilder
. - We set the
BlobSasPermissions
toRead
, since we want to allow the client to download the blob. - We generate the SAS token by calling
ToSasQueryParameters()
on theBlobSasBuilder
object and passing in the account key. - We construct the blob URL with the SAS token and add it to the list of blobs.
- After all the blobs have been processed, we return the list of blob URLs to the client.
That’s it! With this code, you can easily generate SAS tokens for your blobs and send a list of URLs back to the client. The client can then use these URLs to download the blobs from the container.
Application Source Code @ LearnSmartCoding GitHub
Check out other topics that might interest you.
- Automating API Requests with C# and Azure Functions using HttpTrigger.
- Getting Started with Azure Durable Functions: An Example of Function Chaining
- Building an Azure Function with Input Binding to Read and Process Excel Files from Azure Blob Storage
Conclusion
In conclusion, generating SAS tokens for Azure Blob Storage in C# is a straightforward process that provides temporary access to your blobs or containers without sharing your storage account access key. We have explored how to generate SAS tokens and return URLs to download blobs using these tokens. By implementing these concepts, you can enhance the security of your data and provide temporary access to authorized users. Azure Blob Storage is a reliable and scalable platform for storing and managing unstructured data in the cloud, and with the help of C# and SAS tokens, developers can build powerful applications that interact with their blobs and containers programmatically.