Creating Shared Access Signatures
Complete the full lesson to earn 25 points
Work through each section, then tap “Mark as Complete” on the last one.
Lesson: Implementing Shared Access Signatures (SAS) in Azure
Introduction: The Architecture of Granular Access
In the world of cloud storage, managing who can access your data is the most critical component of security. Traditionally, if you wanted to grant someone access to a file in Azure Storage, you would provide them with your account access key. However, this approach is fundamentally flawed because it provides full, unrestricted administrative access to the entire storage account. If that key is compromised, an attacker has complete control over every container, blob, and file within that account.
Shared Access Signatures (SAS) solve this problem by providing a secure, time-limited, and permission-restricted way to grant access to specific resources. Instead of giving away the "master key" to your storage account, you create a signed URL that acts as a temporary token. This token tells the Azure storage service exactly what the user is allowed to do, which specific resource they can touch, and when their permission will expire. This is the foundation of the Principle of Least Privilege in cloud storage.
Understanding SAS is not just about knowing how to generate a string; it is about understanding how to delegate access safely without exposing your infrastructure. Whether you are building a mobile app that needs to upload photos, a backend service that provides temporary download links for reports, or a data pipeline that processes logs, SAS is the tool you will use to manage that communication securely.
The Mechanics of a Shared Access Signature
A Shared Access Signature is essentially a URI that includes a set of query parameters. These parameters dictate the scope of the access, the permissions granted, and the validity period of the token. When a client makes a request to Azure Storage using this URL, the storage service validates the signature against the account key or the user's identity. If the parameters match the request and the signature is valid, the request is processed.
To understand how this works, we must look at the anatomy of a SAS URI. It typically follows this structure:
https://mystorageaccount.blob.core.windows.net/mycontainer/myblob.txt?sv=2023-01-03&ss=b&srt=sco&sp=rwdlac&se=2024-12-31T00:00:00Z&sig=base64encodedstring
The components are:
- sv (Storage Version): The version of the storage service used to sign the SAS.
- sp (Shared Permissions): The specific operations allowed (e.g., read, write, delete).
- se (Shared Expiry): The UTC date and time when the token stops working.
- st (Shared Start): The optional UTC date and time when the token becomes valid.
- sig (Signature): The cryptographic hash that ensures the URL has not been tampered with.
Callout: SAS vs. Account Keys Think of an Account Key as the master key to your entire house—it opens every door, every safe, and every room. A Shared Access Signature is like giving a guest a temporary keycard that only opens the front door for two hours. If that guest loses the card, they cannot access the rest of your house, and the card automatically stops working after the time limit expires.
Types of Shared Access Signatures
Azure provides three distinct types of SAS, each serving a different use case. Choosing the right one is essential for maintaining a strong security posture.
1. User Delegation SAS
This is the most secure method currently available. Instead of being signed with an account key, it is signed with your Microsoft Entra ID (formerly Azure AD) credentials. Because it is tied to an identity rather than a static key, you can revoke access by simply changing the permissions of the user or service principal.
2. Service SAS
This is the traditional way to delegate access to a specific resource (blob, queue, table, or file). It is signed using the storage account key. Because it relies on the account key, if you rotate the account key, all Service SAS tokens generated with that key are immediately invalidated.
3. Account SAS
An Account SAS provides access to resources across multiple services within the storage account. For example, you could grant access to both Blobs and Tables simultaneously. This is the most permissive type of SAS and should be used sparingly, as it increases the blast radius of a potential compromise.
Step-by-Step: Generating a Service SAS
For most developers, the Service SAS is the starting point. Let’s walk through the process of generating one using the Azure CLI. While you can generate these in the portal, doing so via the CLI or code allows for automation.
Prerequisites
- An existing Azure Storage Account.
- The Azure CLI installed and authenticated.
Step 1: Define the Expiry
You must always set an expiry time. A common mistake is creating a SAS that never expires or lasts for years. Aim for the shortest duration possible.
Step 2: Use the CLI to Generate the Token
Run the following command to generate a SAS for a specific blob:
az storage blob generate-sas \
--account-name mystorageaccount \
--container-name mycontainer \
--name myblob.txt \
--permissions r \
--expiry 2024-12-31T00:00:00Z \
--auth-mode login
Explanation of the CLI flags:
--permissions r: We are granting read-only access.--auth-mode login: We are using our Entra ID identity to authorize the creation of the SAS, rather than passing the account key in the command.
Tip: Use UTC Always Always define your start and expiry times in UTC. Azure uses UTC internally, and using local time zones can lead to confusing "token not yet valid" or "token expired" errors that are difficult to debug.
Implementing SAS in Application Code
Hardcoding SAS tokens in your application is a security risk. Instead, your backend should generate SAS tokens on-the-fly when a user requests access to a specific resource. This ensures that the token is short-lived and unique to that user's session.
Below is an example using the Azure Storage Blobs library for .NET.
using Azure.Storage.Blobs;
using Azure.Storage.Sas;
public string GetBlobSasUri(string connectionString, string containerName, string blobName)
{
var blobServiceClient = new BlobServiceClient(connectionString);
var blobClient = blobServiceClient.GetBlobContainerClient(containerName).GetBlobClient(blobName);
// Create a SAS builder
var sasBuilder = new BlobSasBuilder
{
BlobContainerName = containerName,
BlobName = blobName,
Resource = "b", // 'b' for blob
ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(15) // Short-lived token
};
// Set permissions
sasBuilder.SetPermissions(BlobSasPermissions.Read);
// Generate the URI
var sasUri = blobClient.GenerateSasUri(sasBuilder);
return sasUri.ToString();
}
Why this approach is effective:
- Dynamic Generation: The token is created only when requested.
- Short TTL: The token expires in 15 minutes, significantly reducing the window of opportunity for an attacker.
- Encapsulation: The storage account key never leaves your secure backend server.
Comparison of SAS Types
| Feature | User Delegation SAS | Service SAS | Account SAS |
|---|---|---|---|
| Signing Key | Microsoft Entra ID | Account Access Key | Account Access Key |
| Revocation | Easy (via Identity) | Hard (requires key rotation) | Hard (requires key rotation) |
| Scope | Single Resource | Single Service (Blob/File) | Multiple Services |
| Security Level | Highest | Medium | Lowest |
Best Practices for SAS Management
Security is not a "set it and forget it" process. When implementing Shared Access Signatures, follow these industry-standard practices to ensure your data remains protected.
1. Enforce HTTPS
Never, under any circumstances, allow SAS tokens to be transmitted over HTTP. If a token is intercepted over an unencrypted connection, the attacker can use that token as easily as the legitimate user. You can enforce this in the SAS builder by ensuring the protocol parameter is set to https.
2. The Principle of Least Privilege
Do not grant more permissions than necessary. If a user only needs to download a file, grant read access. Never grant write, delete, or list permissions unless the business logic explicitly requires it. If you have a choice between granting access to a container or a single blob, always choose the single blob.
3. Keep Expiry Times Short
The longer a SAS token is valid, the greater the risk. For web applications, a token lifespan of 15 to 60 minutes is usually sufficient. If a user needs a longer session, have your application refresh the SAS token in the background rather than issuing one long-lived token.
4. Use Stored Access Policies
A Stored Access Policy is a server-side resource that groups SAS parameters. By associating a SAS with a policy, you can modify or revoke the access permissions even after the SAS has been distributed. If you detect a breach, you can simply delete the policy, and all associated SAS tokens will immediately become invalid.
Callout: Stored Access Policies vs. Ad-Hoc SAS An Ad-Hoc SAS is "fire and forget"—once you generate the string, you lose control over it until it expires. A Stored Access Policy acts as a "kill switch." If you suspect a token has been leaked, you can update the policy to change the expiry time to the current moment, effectively revoking access for everyone using that policy.
Common Pitfalls and How to Avoid Them
Even with the best intentions, developers often fall into traps that compromise the security of their storage accounts.
Pitfall 1: Leaking SAS in Client-Side Code
Never generate SAS tokens inside your client-side JavaScript or mobile application code. To do this, you would need to store the Storage Account Key in the client application, which makes it visible to anyone who inspects the app bundle. Always generate SAS tokens on a secure backend server.
Pitfall 2: Over-permissioning
It is tempting to simply grant "full control" to simplify development. However, this is a major security vulnerability. If you find yourself constantly using rwdlac (read, write, delete, list, add, create), take a step back and identify the specific operations required for that user flow.
Pitfall 3: Ignoring Revocation
Many teams ignore the need for a revocation strategy. If you rely solely on ad-hoc SAS, you have no way to stop a compromised token. Always implement Stored Access Policies if your application handles sensitive data. This provides a safety net that could save your organization from a significant data breach.
Pitfall 4: Hardcoding Secrets
Never store your storage account connection string or primary keys in source control (e.g., Git). Use Azure Key Vault to store these sensitive values and inject them into your application at runtime.
Troubleshooting SAS Issues
When a SAS token fails, it usually manifests as a 403 Forbidden error. This is a generic error, but it almost always points to one of the following:
- Time Mismatch: The client's clock is out of sync with the server, or the token's start time is in the future.
- Permission Mismatch: The operation being attempted (e.g.,
DELETE) is not permitted by the permissions granted in the SAS string (e.g.,r). - Invalid Signature: The signature was generated incorrectly or the storage key used to sign it has been rotated.
- Incorrect Resource: The SAS was generated for a blob, but the client is trying to access a container or a different blob.
To debug, always log the full request URI and the exact error response from the storage service. Azure provides detailed error codes in the response body that can help you identify exactly which parameter is causing the failure.
Advanced Security: IP Address Restriction
A powerful, yet underutilized, feature of SAS tokens is the ability to restrict access to specific IP addresses or IP ranges. If you know that your users will always be accessing a resource from a specific corporate VPN or a known server farm, you can include the sip parameter in your SAS.
// Example of restricting access to a specific IP range
sasBuilder.IPAddressOrRange = new IPAddressRange("192.168.1.0/24");
If the request comes from an IP address outside that range, the storage service will deny the request, even if the signature is perfectly valid. This adds an extra layer of defense that makes stolen tokens useless if used from a different network.
Summary and Key Takeaways
Implementing Shared Access Signatures is a fundamental skill for any cloud developer. By moving away from static account keys and adopting a model of granular, time-bound delegation, you significantly reduce the attack surface of your applications.
Key Takeaways:
- Delegation over Exposure: Never share your storage account keys. Always generate SAS tokens to delegate access to specific resources.
- Short Lifespans: Keep SAS token expiry times as short as possible to minimize the impact of a potential leak.
- Identity-Based Security: Whenever possible, use User Delegation SAS, which leverages Microsoft Entra ID and offers better security and easier revocation.
- Use Stored Access Policies: Implement policies to provide a "kill switch" for your tokens, allowing you to revoke access immediately if a security incident occurs.
- Backend Generation: Always generate SAS tokens on a secure backend server. Never include the logic for token generation in client-side code that could expose your secret keys.
- HTTPS Only: Ensure that your SAS tokens are only used over encrypted channels (HTTPS) to prevent interception.
- Principle of Least Privilege: Grant only the specific permissions needed for the task at hand. Avoid broad permissions like "full control" at all costs.
By following these principles, you ensure that your Azure storage environment remains secure, compliant, and resilient against unauthorized access. Remember that security is an ongoing process, not a one-time configuration; regularly audit your SAS usage and rotate your storage keys as a standard maintenance practice.
Enjoying the courses?
Everything stays free. Pro shows fewer ads, doubles your daily points limit so you progress twice as fast, and lets you read each lesson on one page.
- ✓ Fewer advertisements
- ✓ 2× daily points limit
- ✓ Distraction-free lessons