Sequence 6 โ Authorization Foundations: Access Keys & SAS
Prerequisites: Sequences 1-5 (storage account anatomy, data plane, AzCopy/Storage Explorer). ยท What you'll be able to do: (1) name the four ways to authorize data access and which service each supports; (2) rotate and protect account access keys without downtime; (3) pick the right SAS type and read a SAS token's anatomy; (4) revoke access with stored access policies and cap SAS lifetime with an expiration policy. ยท Est. time: ~16 min.
1. Two planes, one focus: authorizing DATA access
Azure Storage has two distinct permission surfaces. The control plane (managing the account resource itself โ create, delete, configure) is governed by Azure RBAC on the management API. The data plane (reading and writing blobs, files, queues, tables) is what this episode covers. Every request to a secure resource over HTTP/HTTPS must be authorized โ by default nothing is anonymous.
There are four ways to authorize data operations:
Microsoft Entra ID (with managed identities + Azure RBAC) is the Microsoft-recommended method everywhere it is supported, because no secret is stored in code. Entra RBAC role assignment detail is Sequence 7; network rules that gate access are Sequence 8.
Which method works for which service?
| Authorization method | Blob | Files | Queue | Table | Secured with |
|---|---|---|---|---|---|
| Microsoft Entra ID | Yes | Yes* | Yes | Yes | Identity + RBAC |
| Shared Key (account key) | Yes | Yes | Yes | Yes | The account access key |
| User delegation SAS | Yes | Yes | Yes | Yes | Entra user delegation key |
| Service SAS | Yes | Yes | Yes | Yes | Account key (Shared Key) |
| Account SAS | Yes | Yes | Yes | Yes | Account key (Shared Key) |
| Anonymous read | Yes | No | No | No | Nothing (public) |
* Entra ID for Azure Files (SMB) uses Microsoft Entra Domain Services, Microsoft Entra Kerberos (hybrid identities), or on-premises AD DS โ covered in Sequence 9.
Correction / currency note: Older AZ-104 material says "user delegation SAS is Blob-only." Current Azure docs (2026) state the user delegation SAS is supported for Blob, Queue, Table, and Azure Files. Either way, user delegation SAS remains the recommended SAS type because it is Entra-signed, not key-signed.
2. Account access keys: the master credentials
When you create a storage account, Azure generates two 512-bit access keys: key1 and key2. Each key:
- Authorizes Shared Key requests against the account, and can sign service and account SAS tokens.
- Grants full access to ALL data in the account โ there is no granularity, no per-container scope, no auditing of who used the key. Anyone holding a key effectively is the storage account.
A connection string bundles the account name + a key (and endpoints) into one string your app can consume. The portal shows a ready-made connection string per key.
Viewing keys requires the action Microsoft.Storage/storageAccounts/listkeys/action โ built-in roles Owner, Contributor, and Storage Account Key Operator Service Role include it.
az storage account keys list \
--resource-group <resource-group> \
--account-name <storage-account>
$key = (Get-AzStorageAccountKey -ResourceGroupName <resource-group> `
-Name <storage-account>).Value[0] # Value[1] = second key
Why two keys? Zero-downtime rotation
Two keys exist so you can rotate without an outage. The pattern is a leap-frog:
The golden rule: use only ONE key across all your apps at a time. If some apps use key1 and others key2, you can never regenerate either without breaking something.
az storage account keys renew \
--resource-group <resource-group> \
--account-name <storage-account> \
--key primary # then repeat with --key secondary
New-AzStorageAccountKey -ResourceGroupName <resource-group> `
-Name <storage-account> -KeyName key1 # then key2
Critical side effect of rotation: Regenerating a key immediately revokes every service SAS and account SAS signed with that key. You must re-issue those SAS tokens afterward. User delegation SAS are NOT affected (they are Entra-signed, not key-signed) โ another reason to prefer them.
Protecting and auditing keys
| Practice | Why it matters |
|---|---|
| Store keys in Azure Key Vault | Centralized secret management; Key Vault can rotate keys without app interruption. |
| Prefer Entra ID + managed identities | No secret in code at all โ the best outcome. |
| Set a key expiration policy | --key-exp-days / -KeyExpirationPeriodInDay sets a rotation reminder (in days). Not auto-rotation โ it flags overdue keys. |
| Audit with Azure Policy | Built-in policy "Storage account keys should not be expired" reports non-compliant accounts. |
| Disallow Shared Key authorization | The strongest control โ see below. |
Note: You may need to rotate each key once before a key expiration policy (or a SAS expiration policy) can be set โ older accounts have a null
keyCreationTime.
Disabling Shared Key
You can disallow Shared Key authorization on the account. When disabled, clients must use Entra ID or a user delegation SAS โ service/account SAS (key-signed) stop working too. This is Microsoft's recommended hardening step. (Detail and the allowSharedKeyAccess property continue in later security sequences.)
3. Shared access signatures (SAS): scoped, time-boxed delegation
A SAS is a signed URL that grants limited, delegated access to storage resources. It answers three questions: what resources, what permissions, for how long. A SAS lets a client talk to storage directly (no front-end proxy in the data path) while you still control the grant.
The three SAS types
| User delegation SAS | Service SAS | Account SAS | |
|---|---|---|---|
| Signed with | Entra user delegation key | Account key (Shared Key) | Account key (Shared Key) |
| Scope | One service's resources | One service only | One or more services |
| Service-level ops (Get/Set Service Properties, Get Service Stats) | No | No | Yes |
| Stored access policy? | No (ad hoc only) | Yes (optional) | No (ad hoc only) |
| Survives key rotation? | Yes | No | No |
| Recommendation | PREFERRED | Use only if needed | Use only if needed |
- User delegation SAS โ secured by a user delegation key obtained with Entra credentials. Creating it requires the RBAC action
Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey. No account key touches your code. Has a hard maximum lifetime of 7 days (tied to the user delegation key). - Service SAS โ delegates access to one resource in one service. Can be tied to a stored access policy (see ยง5).
- Account SAS โ broadest: multiple services, plus service-level operations and operations a service SAS can't do (e.g., create/delete containers). Most powerful, so most dangerous if leaked.
How a SAS is authorized
| Type of SAS | Authorized via |
|---|---|
| User delegation SAS | Microsoft Entra ID |
| Service SAS | Shared Key |
| Account SAS | Shared Key |
When a request arrives with a SAS, Azure Storage validates the signature and parameters. Valid โ request authorized. Invalid/expired โ HTTP 403 (Forbidden).
Security reality: SAS generation cannot be audited โ anyone with the account key (or the right Entra role) can mint a SAS silently. SAS tokens are created client-side, are never tracked by Azure, and there is no API to count or list them. This is the core argument for disallowing Shared Key and preferring Entra-signed user delegation SAS.
4. Anatomy of a SAS token
A SAS is the query string appended to a resource URI, after the ? delimiter (the ? is not part of the token itself):
https://mystorage.blob.core.windows.net/photos/cat.jpg?sp=r&st=2026-06-29T09:00:00Z&se=2026-06-29T10:00:00Z&spr=https&sip=203.0.113.5&sv=2024-11-04&sr=b&sig=Base64Signature%3D
| Field | Param | Meaning | Best practice |
|---|---|---|---|
| Signed permissions | sp | e.g. r read, w write, d delete, l list | Least privilege โ read-only when possible |
| Signed start | st | When the SAS becomes valid | Leave unset, or set ~15 min in the past (clock skew) |
| Signed expiry | se | When the SAS stops working | Short / near-term |
| Signed resource | sr | Resource type: b blob, c container, etc. | Narrowest scope |
| Signed IP | sip | Allowed IP or range | Restrict to known callers |
| Signed protocol | spr | https (or https,http) | HTTPS only |
| Signed version | sv | Storage REST API version | Current version |
| Signature | sig | HMAC of the fields, signed by the key | The actual proof โ never share over HTTP |
Clock skew: machines differ by up to ~15 minutes. Set
st15 min in the past (or omit it), and don't makeseso tight it fails for early-arriving clients.
5. Stored access policies: server-side control & REVOCATION
An ad hoc SAS bakes start/expiry/permissions into the URL โ once issued, the only way to revoke it early is to regenerate the account key (nuclear: kills all key-signed SAS).
A stored access policy moves those constraints onto the resource (a blob container, file share, queue, or table). A service SAS can then reference the policy by name and inherit its start time, expiry, and permissions.
Why it matters:
- Revoke before expiry โ delete or rename the policy and every SAS bound to it dies instantly, without rotating keys.
- Central management โ change permissions/expiry in one place for many SAS.
- Limit: max 5 stored access policies per container (or share/queue/table).
- Only service SAS can use stored access policies. User delegation and account SAS are ad hoc only.
Pattern: set the stored access policy expiry far in the future (so SAS keep working) and rely on the policy's existence as the on/off switch โ delete it to revoke.
6. SAS expiration policy: capping lifetime at the account level
Separate from a stored access policy, the SAS expiration policy is an account-level setting that defines a recommended maximum validity interval for any SAS minted on the account. Format: <days>.<hours>:<minutes>:<seconds> (e.g. 1.12:05:06).
How it's evaluated: validity = se (signed expiry) โ st (signed start). With a policy in effect, the signed start (st) field becomes required on every SAS. The policy has two actions:
| Action | Behavior | Use when |
|---|---|---|
| Log (default) | Out-of-policy SAS still works; a SasExpiryStatus entry is written to logs (needs Azure Monitor diagnostics). | Auditing / discovery without breaking workflows |
| Block | Out-of-policy SAS is denied. Strictest enforcement. | Zero-tolerance organizations (recommended end state) |
# Set the maximum allowed SAS lifetime (period format DD.HH:MM:SS).
# The enforcement ACTION (Log vs Block โ see table above) is part of the SAS policy:
# set it in the portal, or via the SasPolicy ARM property shown below.
az storage account update \
--name <storage-account> --resource-group <resource-group> \
--sas-exp 1.12:05:06
{
"SasPolicy": {
"expirationAction": "Block",
"sasExpirationPeriod": "1.12:05:06"
}
}Gotchas:
- Applies to all three SAS types, but Block is NOT supported for user delegation SAS over the HDFS endpoint or for service SAS using a stored access policy.
- A user delegation SAS still caps at 7 days regardless of the policy; a policy > 7 days has no effect on it.
- Azure File Sync needs โฅ 3-day SAS โ set the upper limit to 3 days or more or sync/recall breaks (relevant to Sequence 13).
- You may need to rotate both keys once before the policy can be set.
- Monitor compliance with the built-in Azure Policy "Storage accounts should have shared access signature (SAS) policies configured."
7. Best practices (the exam-favorite list)
- Prefer Entra ID + managed identities; when you must use SAS, prefer user delegation SAS.
- HTTPS only when creating/distributing a SAS (prevents man-in-the-middle theft).
- Least privilege + narrowest resource + near-term expiry.
- Have a revocation plan: stored access policy (delete to revoke) or, last resort, key rotation.
- Set a SAS expiration policy (Log โ then Block) and a key expiration policy.
- Disallow Shared Key where possible; store any keys in Key Vault.
- Remember billing: you pay for all SAS-driven egress/ingress โ leaked write+read SAS can be costly.
Key takeaways
- 4 data-auth methods: Entra, Shared Key, SAS, Anonymous (blob-only). Mnemonic: "ESSA" โ Entra first, Anonymous last.
- Two keys exist for rotation, not for splitting traffic โ one key everywhere at a time, leap-frog to rotate, zero downtime.
- Account key = full access, no audit. Rotate it and all key-signed SAS die (service + account); user delegation SAS survive.
- 3 SAS types: User delegation (Entra-signed, preferred, 7-day cap), Service (key, single service, can use stored policy), Account (key, multi-service, most powerful). Mnemonic: "USA".
- SAS anatomy:
sp se st sr sip spr sv sigโ permissions, expiry, start, resource, IP, protocol, version, signature. - Stored access policy = server-side, revoke without key rotation, max 5 per container, service SAS only.
- SAS expiration policy = account-level max lifetime; Log (warn) vs Block (enforce); forces
st.
Exercises
- Recall: A storage account has how many access keys, and what is the primary purpose of having that number?
- Recall: Which SAS type is signed with Microsoft Entra credentials, and what RBAC action is required to create it?
- Applied: An admin regenerates key1. A web app authenticating with the account key keeps working, but a partner's download links suddenly return HTTP 403. Explain why, and which SAS type would have been unaffected.
- Applied: You distributed a service SAS valid until 2027 and now must revoke it today without disrupting other apps that use the account key. What mechanism do you use, and what is the prerequisite at SAS-creation time?
- Scenario: Security policy demands that no SAS on the account can be valid for more than 24 hours, and that any attempt to use a longer one is denied. Name the feature, the action you choose, one field it forces onto every SAS, and one SAS type for which enforcement won't apply.
- Recall/Trap: True or false โ making blobs publicly readable requires issuing a SAS to every client. Correct it if false.
Answers
- Two keys (key1 and key2). Their purpose is zero-downtime rotation: move all apps to the other key, regenerate the first, switch back, then regenerate the second. (Use only one key across apps at a time.)
- User delegation SAS, signed with a user delegation key obtained from Entra. Creating it requires
Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey. - Regenerating key1 revokes every service and account SAS signed with that key โ the partner links were key-signed SAS, hence 403. The web app uses the live key (or was switched to key2), so it keeps working. A user delegation SAS (Entra-signed) would have been unaffected by key rotation.
- Use a stored access policy referenced by the service SAS, then delete (or rename) the policy โ this instantly revokes all SAS bound to it without touching the account keys. Prerequisite: the service SAS must have been created referencing that stored access policy (ad hoc SAS can't be revoked this way). (Account keys must remain valid for other apps.)
- Feature: SAS expiration policy (account-level). Set the upper limit to
1.00:00:00(1 day) with action Block. It forces the signed start (st) field onto every SAS. Enforcement (Block) does not apply to a service SAS that uses a stored access policy (nor to user delegation SAS over the HDFS endpoint). - False. To make all blobs in a container publicly readable, enable anonymous public read on the container instead of issuing a SAS per client. (Note: Microsoft recommends disabling anonymous access generally โ see Sequence 7.)
Coming up next
Sequence 7 โ Microsoft Entra ID, RBAC & Anonymous Access: how identity-based authorization actually works โ assigning Azure built-in storage data roles, scoping them, and safely remediating anonymous public read.