Encrypt Online
Theme

Certificates & Site Ops

Fix Azure SAS Token 403 Errors: Expiry, Permissions, and Scope

Debug Azure Blob SAS 403 errors by checking expiry, permissions, resource scope, and encoding. Separate token problems from Azure policy and network failures.

Encrypt Online Editorial Team6 min read
Encrypt Online guide cover on a sand background with the headline Fix Azure SAS errors. The established protected-link glyph represents the shared access URL.

For an Azure Storage SAS URL returning HTTP 403, read the error code in the response. With AuthenticationFailed, check the token's dates, fields, and signature. With AuthorizationPermissionMismatch, compare the permissions with the operation that failed.

Paste the URL or query string into the Azure SAS Token Debugger to read its expiry, permissions, and resource scope. Choose the Blob operation your application sends to compare the required permissions. A SAS token grants access to a resource; it doesn't encrypt the blob.

AuthenticationFailed and other SAS error codes

Look for x-ms-error-code in the response headers and Code in the XML body. Keep the request time and request ID alongside it so you can find the request in Storage logs.

Error code First useful check
AuthenticationFailed Dates, malformed fields, changed URL, or signing-key changes
AuthorizationPermissionMismatch Permission required by the actual operation
AuthorizationResourceTypeMismatch Account SAS resource types in srt
AuthorizationServiceMismatch Account SAS services in ss
AuthorizationSourceIPMismatch Request source IP against sip
AuthorizationProtocolMismatch HTTP versus the protocol allowed by spr

Microsoft's SAS error reference describes these failures.

For an existing GET download URL, capture the response from a small test blob with:

Shell
curl --silent --show-error --dump-header ./response-headers.txt \
  --output ./response-body.bin "$SAS_URL"

This saves the response body: blob content if the download succeeds, usually XML if it fails. Keep the URL quoted so the shell does not split it at &.

Start time, expiry, and delegation-key lifetime

st is the signed start time and se is the signed expiry. A token with st in the future is not ready to use; a token past se has expired. Compare with the failed request's time, especially when investigating yesterday's incident rather than testing now.

For example, a token might contain:

Text
st=2026-10-02T12:00:00Z
se=2026-10-02T12:30:00Z

A request at 11:59 UTC is too early; one at 12:31 UTC is too late. Convert local log timestamps to UTC before comparing them. Allow for clock skew when creating tokens, as described in Microsoft's SAS timing guidance.

st is normally optional, but a storage account's SAS expiration policy can require it. With the Block action, requests subject to that policy fail when st is missing or the validity interval exceeds the configured limit. Check the account's policy before omitting st to work around clock skew. SAS expiration policy

Tip: Save the REST operation and UTC timestamp with each failed request. They let you compare yesterday's failure with the token's permissions and expiry, even if a test works today.

A user-delegation SAS also has a delegation-key lifetime, skt through ske. Check ske as well as se: the SAS stops working when its delegation key expires, even if se is later. See the user-delegation SAS reference for both sets of fields.

Blob downloads and container listings

The sp value contains permission letters. For ordinary Blob operations, r reads a blob and l lists blobs. A download and a container listing both use GET, so the HTTP method alone is not enough.

A read-only blob SAS can download its blob but cannot enumerate its container. A List Blobs request targets the container and includes restype=container&comp=list; a service SAS needs container scope and list permission. List Blobs authorization

For an account SAS, inspect both ss and srt. Blob requests need b in ss. The srt resource types distinguish service (s), container (c), and object (o) operations, so a token that allows reading an object may still lack the scope needed to list containers. See account SAS permissions and resource types.

Uploads that fail when the SDK switches to blocks

A create-only SAS can work for a small upload and fail for a larger one. Creating a new blob with Put Blob accepts c or w. Overwriting a blob requires w, and staging blocks with Put Block also requires w. Check whether the SDK switched from Put Blob to Put Block, then request a token with the permission that operation needs. Put Blob, Put Block

Changing sp=r to sp=rw in an existing URL does not grant write access. Those fields participate in the signature. Have the issuer create a new SAS for the intended operation.

Missing sp or se when the token names a stored policy

When si names a stored access policy, some permissions or dates may come from that policy rather than the URL. A missing se or sp is therefore not automatically a broken service SAS.

Ask the container owner to inspect the policy named by si in Azure. Its current permissions and dates aren't included in the token. Deleting or changing the policy can stop a previously working SAS, and changes can take a short time to propagate. See the stored access policy reference.

For a SAS signed with an account key, also check whether that key was rotated after the token was created.

Changed paths, plus signs, and double encoding

Compare the value returned by the issuer with the value sent by the client. Copying through HTML can introduce literal &; a form decoder can turn a plus sign into a space; an extra encoding pass can turn %2B into %252B. Inspect the differences before rebuilding the URL.

Do not rearrange the blob path or substitute another account's hostname. The signed resource is part of SAS construction. Use an Azure SDK or Storage Explorer to generate the token when checking custom signing code. Service SAS construction

Network rules and container encryption policies

For AuthorizationFailure, check where the failing client runs and which endpoint it resolves. A SAS does not bypass the account's firewall or private endpoint configuration. For KeyBasedAuthenticationNotPermitted, check which authentication method the account requires. Enabling Shared Key may conflict with that policy. Microsoft's 403 troubleshooting guide

For RequestForbiddenByContainerEncryptionPolicy, compare any ses value with the container's encryption-scope policy. If you're using a user-delegation SAS, check the issuing identity's permissions in Azure too. You'll need the account or container configuration for these checks; the URL contains only the signed token fields.