Introduction

Azure Blob Storage returns 403 Forbidden when upload requests lack proper authorization. This can happen with SAS tokens, shared key authentication, or Azure AD role assignments, blocking applications from storing files.

Symptoms

403 Forbidden on upload:

```bash $ az storage blob upload --account-name mystorageaccount \ --container-name mycontainer \ --name test.txt \ --file test.txt

{"Message":"Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature."} ```

SAS token expired error:

```bash $ curl -X PUT "https://mystorageaccount.blob.core.windows.net/mycontainer/test.txt?sv=2023-01-03&ss=b&srt=sco&sp=w&se=2024-01-01T00:00:00Z&st=2024-01-01T00:00:00Z&spr=https&sig=SIGNATURE" \ -H "x-ms-blob-type: BlockBlob" \ --data-binary "@test.txt"

HTTP/1.1 403 Forbidden {"Message":"Signature did not match. String to sign used was..."} ```

Permission denied:

bash
# In application logs:
"Status: 403 (This request is not authorized to perform this operation)"

Common Causes

  1. 1.SAS token expired - Start and expiry time constraints
  2. 2.SAS permission mismatch - Token lacks write permission
  3. 3.IAM role missing - User/service principal lacks Storage Blob Data Contributor
  4. 4.Storage account firewall - Network rules blocking access
  5. 5.Public access disabled - Container requires authentication
  6. 6.Wrong storage key - Using old access key after rotation
  7. 7.CORS issues - Browser requests blocked

Step-by-Step Fix

  1. 1.Check logs for specific error messages
  2. 2.Verify configuration settings
  3. 3.Test network connectivity
  4. 4.Review recent changes
  5. 5.Apply corrective action
  6. 6.Verify the fix

Step 1: Check SAS Token Validity

```bash # Decode SAS token to check parameters # Look at the URL parameters: # sv: Storage version # se: Expiry time # st: Start time # sp: Permissions (should include 'w' for write)

# Check current time is within valid window date -u

# Compare with SAS token times (URL decoded) # se=2024-12-31T23:59:59Z (expiry) # st=2024-01-01T00:00:00Z (start) ```

Step 2: Generate New SAS Token

```bash # Generate new SAS token with write permission az storage container generate-sas \ --account-name mystorageaccount \ --name mycontainer \ --permissions w \ --expiry 2024-12-31T23:59:59Z \ --output tsv

# Generate with account key az storage account keys list \ --account-name mystorageaccount \ --query '[0].value' -o tsv ```

Step 3: Check IAM Role Assignments

```bash # Check current user's role assignments az role assignment list \ --assignee user@example.com \ --scope /subscriptions/SUB/resourceGroups/my-rg/providers/Microsoft.Storage/storageAccounts/mystorageaccount

# Required roles for blob upload: # - Storage Blob Data Contributor (allows read/write/delete) # - Storage Blob Data Owner (full access)

# Assign missing role az role assignment create \ --assignee user@example.com \ --role "Storage Blob Data Contributor" \ --scope /subscriptions/SUB/resourceGroups/my-rg/providers/Microsoft.Storage/storageAccounts/mystorageaccount ```

Step 4: Check Storage Account Firewall

```bash # Check network rules az storage account show \ --name mystorageaccount \ --resource-group my-rg \ --query '{Firewall:networkAcls}'

# If defaultAction is "Deny", only allowed IPs/subnets can access

# Add your IP to allowlist az storage account network-rule add \ --account-name mystorageaccount \ --ip-address YOUR_PUBLIC_IP

# Or allow all Azure services (use with caution) az storage account update \ --name mystorageaccount \ --resource-group my-rg \ --default-action Allow ```

Step 5: Verify Access Key

```bash # List storage account keys az storage account keys list \ --account-name mystorageaccount \ --resource-group my-rg

# Try upload with key az storage blob upload \ --account-name mystorageaccount \ --account-key KEY_VALUE \ --container-name mycontainer \ --name test.txt \ --file test.txt ```

Step 6: Check Public Access Setting

```bash # Check if public access is allowed az storage account show \ --name mystorageaccount \ --resource-group my-rg \ --query 'allowBlobPublicAccess'

# If false, anonymous access is blocked # For private containers, authentication is always required

# Enable public access (if needed) az storage account update \ --name mystorageaccount \ --resource-group my-rg \ --allow-blob-public-access true ```

Step 7: Test with Azure CLI

```bash # Authenticate with Azure AD az login

# Upload using AD authentication az storage blob upload \ --account-name mystorageaccount \ --container-name mycontainer \ --name test.txt \ --file test.txt \ --auth-mode login

# If this works, the issue is with your SAS token or access key ```

Step 8: Check Container ACL

```bash # Check container access level az storage container show \ --account-name mystorageaccount \ --name mycontainer \ --query '{PublicAccess:publicAccess,Metadata:metadata}'

# Possible values: # - container: Public read access for container and blobs # - blob: Public read access for blobs only # - null: No public access (requires authentication) ```

Step 9: Review Activity Logs

bash
# Check storage account activity logs for 403 errors
az monitor activity-log list \
  --resource-group my-rg \
  --caller user@example.com \
  --resource /subscriptions/SUB/resourceGroups/my-rg/providers/Microsoft.Storage/storageAccounts/mystorageaccount \
  --query "[?contains(operationName.value, 'write')].{Time:eventTimestamp, Operation:operationName, Status:status.value}"

Step 10: Check for Conditional Access Policies

```bash # Check Azure AD conditional access policies # Azure Portal > Azure AD > Security > Conditional Access

# Look for policies that: # - Block storage access from certain locations # - Require MFA for storage access # - Restrict access to specific devices

# Policies may block access even with correct permissions ```

Azure Storage Authentication Methods

MethodUse CasePermissions
Access KeyService adminFull access
SAS TokenTime-limited accessScoped permissions
Azure AD RBACUser/service principalRole-based access
Managed IdentityAzure servicesAutomatic credential management

Verification

```bash # After fixing, test upload az storage blob upload \ --account-name mystorageaccount \ --container-name mycontainer \ --name verify.txt \ --file verify.txt \ --auth-mode login

# Verify blob exists az storage blob show \ --account-name mystorageaccount \ --container-name mycontainer \ --name verify.txt \ --query '{Name:name,Size:properties.contentLength}'

# Should return blob metadata ```

  • [Fix Azure Storage Account Inaccessible](/articles/fix-azure-storage-account-inaccessible)
  • [Fix Azure CORS Policy Blocking Calls](/articles/fix-azure-cors-policy-blocking-calls)
  • [Fix Azure SAS Token Invalid](/articles/fix-azure-sas-token-invalid)
  • [Technical troubleshooting: Fix Azure Aks Pod Crashloopbackoff Issue in Azure](azure-aks-pod-crashloopbackoff)
  • [Technical troubleshooting: Fix Azure Api Management Policy Expression Runtime](azure-api-management-policy-expression-runtime-error)
  • [Technical troubleshooting: Fix Azure App Configuration Feature Flag Not Refre](azure-app-configuration-feature-flag-not-refreshing)
  • [Technical troubleshooting: Fix Azure App Service 503 Always On Disabled Issue](azure-app-service-503-always-on-disabled)
  • [Technical troubleshooting: Fix Azure Application Gateway Err SSL Unrecognized](azure-application-gateway-err-ssl-unrecognized-name-alert)

<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "Fix Azure Blob Upload 403 Forbidden", "description": "Troubleshoot Azure Blob Storage 403 forbidden errors during upload. Fix SAS tokens, IAM permissions, and firewall settings.", "url": "https://www.fixwikihub.com/fix-azure-blob-upload-403-forbidden", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2026-04-02T07:09:24.214Z", "dateModified": "2026-04-02T07:09:24.214Z" } </script>