AuthorizationFailure

Azure Blob 403 with Valid SAS Token? Check the Clock

A 403 AuthorizationFailure with a valid SAS token usually means the server time is off or the SAS is scoped wrong. Here's how to fix it fast.

You're testing a download from Azure Blob Storage and you've generated a SAS token that you've double-checked—it looks fine. The URL is right, the container exists, but you get a 403 AuthorizationFailure. The weird part? The token hasn't expired, and you just created it. Sound familiar?

This error often shows up when you're running a script that generates a SAS token on one machine and then uses it on another—say, a dev machine and a server. Or when you're using a SAS token in an app that runs on a VM with a misconfigured clock. The token is valid, but Azure sees it as expired or not yet active because the request time doesn't match.

Root Cause: Clock Skew and SAS Scope

Azure checks the timestamp on the SAS token against the current UTC time on the server. If your client's clock is off by even a few minutes, the token might appear to be from the future or past, triggering an AuthorizationFailure. People rarely suspect their server clock because it's usually the last thing on their mind.

Another common cause is that the SAS token was generated with a specific IP range or protocol (HTTPS only) and your request doesn't match. For example, you might generate a SAS with an IP restriction to your office, then try to use it from a cloud VM—that'll give you a 403 even though the token is technically valid.

The Fix: Step by Step

  1. Check the server clock. On the machine making the request, open a terminal and run date -u (Linux/macOS) or w32tm /stripchart /computer:time.windows.com /samples:1 on Windows. Compare the output to the actual UTC time from a service like time.gov. If it's off by more than a couple of minutes, that's your problem.
  2. Sync the clock. On Linux, use sudo ntpdate pool.ntp.org or enable NTP with sudo timedatectl set-ntp true. On Windows, run w32tm /resync. If you're in a VM, make sure the VM time sync is enabled. For example, in Hyper-V, check integration services. On AWS EC2, the Amazon Time Sync service should be configured.
  3. Verify SAS token scope. Go to the Azure portal, navigate to your storage account, and under "Shared access signature," check the allowed IP addresses and protocols. If you set an IP range, make sure your current public IP falls within it. Also confirm the protocol is HTTPS if you're using an HTTP endpoint (though you should be using HTTPS always).
  4. Regenerate a fresh SAS token. Sometimes the issue is that the start time of the SAS is in the future, even by a few seconds. When generating a SAS programmatically, use a start time of DateTime.UtcNow.AddMinutes(-5) to allow for clock skew. Here's a C# example:
    var sasBuilder = new AccountSasBuilder
    {
        Services = AccountSasServices.Blobs,
        ResourceTypes = AccountSasResourceTypes.Object,
        ExpiresOn = DateTime.UtcNow.AddHours(1),
        StartsOn = DateTime.UtcNow.AddMinutes(-5) // the key fix
    };
  5. Test with a simple tool. Use AzCopy or the Azure Storage Explorer to download the blob with the same SAS URL. If that works, the issue is in your code. If it fails, the token is the problem.

What If It Still Fails?

If the clock is synced, the token scope looks right, and a fresh token still gives a 403, then you're dealing with a different layer. Check these:

  • Storage account firewall. If you've enabled "Allow access from selected networks" on the storage account, and the client IP isn't on the allowlist, you'll get a 403. Even if the SAS is valid, the network rule blocks the request. Go to Networking > Firewalls and virtual networks and add the client's public IP.
  • Shared access policy mismatch. If you're using a stored access policy, make sure the policy exists and hasn't been deleted. A deleted policy will invalidate all SAS tokens that reference it.
  • Signing key rotation. If you've rotated the storage account key after generating the SAS, the token is dead. Regenerate the SAS with the current key.

In my experience, 9 out of 10 times it's the clock. It's such a simple thing that people overlook it, but Azure's time validation is strict. So check that first, and you'll save yourself an hour of head-scratching.

Related Errors in Server & Cloud
HA admission control failure VMware HA Admission Control Failure: Fix in 3 Steps 0X00000437 Fix ERROR_DIFFERENT_SERVICE_ACCOUNT (0X00000437) Fast etcdserver: request timed out Kubernetes etcd Cluster Unreachable – 3 Real Fixes Google Analytics Not Tracking Page Views? Try These Fixes First

Was this solution helpful?

EP
Erropedia Team
Tech Support Editors
The Erropedia editorial team researches and documents real-world tech errors from across Windows, Linux, macOS, networking, databases, cloud platforms, and more. Every solution is reviewed for accuracy and updated as software and systems evolve.