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:

Data request tostorage accountHow is itauthorized?Microsoft Entra ID(identity + RBAC) โ€”RECOMMENDEDShared Key(account access key)Shared access signature(SAS) โ€” signed URLAnonymous public read(blobs only) โ€” discouragedUser delegation SAS(Entra-signed)Service SAS(key-signed)Account SAS(key-signed)

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 methodBlobFilesQueueTableSecured with
Microsoft Entra IDYesYes*YesYesIdentity + RBAC
Shared Key (account key)YesYesYesYesThe account access key
User delegation SASYesYesYesYesEntra user delegation key
Service SASYesYesYesYesAccount key (Shared Key)
Account SASYesYesYesYesAccount key (Shared Key)
Anonymous readYesNoNoNoNothing (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:

Storage accountAppStorage accountAppNormally apps use key1Both keys now fresh, no downtime1. Switch apps to key22. Regenerate key13. Switch apps back to key1 (new value)4. Regenerate key2

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

PracticeWhy it matters
Store keys in Azure Key VaultCentralized secret management; Key Vault can rotate keys without app interruption.
Prefer Entra ID + managed identitiesNo 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 PolicyBuilt-in policy "Storage account keys should not be expired" reports non-compliant accounts.
Disallow Shared Key authorizationThe 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 SASService SASAccount SAS
Signed withEntra user delegation keyAccount key (Shared Key)Account key (Shared Key)
ScopeOne service's resourcesOne service onlyOne or more services
Service-level ops (Get/Set Service Properties, Get Service Stats)NoNoYes
Stored access policy?No (ad hoc only)Yes (optional)No (ad hoc only)
Survives key rotation?YesNoNo
RecommendationPREFERREDUse only if neededUse 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 SASAuthorized via
User delegation SASMicrosoft Entra ID
Service SASShared Key
Account SASShared 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
FieldParamMeaningBest practice
Signed permissionsspe.g. r read, w write, d delete, l listLeast privilege โ€” read-only when possible
Signed startstWhen the SAS becomes validLeave unset, or set ~15 min in the past (clock skew)
Signed expiryseWhen the SAS stops workingShort / near-term
Signed resourcesrResource type: b blob, c container, etc.Narrowest scope
Signed IPsipAllowed IP or rangeRestrict to known callers
Signed protocolsprhttps (or https,http)HTTPS only
Signed versionsvStorage REST API versionCurrent version
SignaturesigHMAC of the fields, signed by the keyThe actual proof โ€” never share over HTTP

Clock skew: machines differ by up to ~15 minutes. Set st 15 min in the past (or omit it), and don't make se so 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.

Container / share / queue / tablereferencesedit or DELETE policy= instant revocationof all SAS using itStored access policyname: readonly2026perms: rexpiry: far futureService SASsr=b ... si=readonly2026Admin

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:

ActionBehaviorUse 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
BlockOut-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

  1. Recall: A storage account has how many access keys, and what is the primary purpose of having that number?
  2. Recall: Which SAS type is signed with Microsoft Entra credentials, and what RBAC action is required to create it?
  3. 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.
  4. 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?
  5. 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.
  6. Recall/Trap: True or false โ€” making blobs publicly readable requires issuing a SAS to every client. Correct it if false.
Answers
  1. 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.)
  2. User delegation SAS, signed with a user delegation key obtained from Entra. Creating it requires Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey.
  3. 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.
  4. 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.)
  5. 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).
  6. 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.