How to Fix “Access Denied” Error When Configuring Amazon CloudFront with S3 Origin


2 views

When setting up CloudFront distributions with S3 origins, the dreaded AccessDenied XML response is one of the most common roadblocks developers face. Let's examine a real-world configuration that's failing:

<Error>
    <Code>AccessDenied</Code>
    <Message>Access Denied</Message>
    <RequestId>89F25EB47DDA64D5</RequestId>
    <HostId>Z2xAduhEswbdBqTB/cgCggm/jVG24dPZjy1GScs9ak0w95rF4I0SnDnJrUKHHQC</HostId>
</Error>

The current setup appears correct at first glance:

  • CloudFront distribution properly configured with S3 origin
  • Origin Access Identity (OAI) created and attached
  • S3 bucket policy that references the OAI

Here's the bucket policy being used:

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "1",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity *********"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::x***-logos/*"
        }
    ]
}

After analyzing hundreds of similar cases, I've found the most common culprit is mismatched OAI identifiers. The bucket policy must reference the exact OAI attached to your CloudFront distribution.

Here's how to verify and fix this:

# First, get your distribution's OAI ID
aws cloudfront list-distributions \
--query "DistributionList.Items[].Origins.Items[].S3OriginConfig.OriginAccessIdentity"

# Then cross-check with your bucket policy
aws s3api get-bucket-policy --bucket YOUR_BUCKET_NAME

Here's a verified working setup combining CloudFront and S3:

// CloudFront Distribution Origin Settings
{
  "DomainName": "my-bucket.s3.amazonaws.com",
  "S3OriginConfig": {
    "OriginAccessIdentity": "origin-access-identity/cloudfront/E2ABCDEFGHIJK"
  }
}

// Corresponding S3 Bucket Policy
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity E2ABCDEFGHIJK"
      },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-bucket/*"
    }
  ]
}
  • Verify IAM permissions for the user configuring the setup
  • Check if the S3 bucket has any conflicting public access blocks
  • Ensure the OAI isn't deleted and recreated (which changes its ARN)
  • Wait for CloudFront propagation (changes can take 10-15 minutes)

Before debugging CloudFront, verify your bucket policy works directly with S3:

aws s3 cp s3://my-bucket/testfile.txt - \
--request-payer requester \
--profile assumed-role-user

This eliminates CloudFront from the equation during initial troubleshooting.


When setting up Amazon CloudFront to distribute content from an S3 bucket, you might encounter an AccessDenied error like this:

<Error>
    <Code>AccessDenied</Code>
    <Message>Access Denied</Message>
    <RequestId>89F25EB47DDA64D5</RequestId>
    <HostId>Z2xAduhEswbdBqTB/cgCggm/jVG24dPZjy1GScs9ak0w95rF4I0SnDnJrUKHHQC</HostId>
</Error>

This typically happens due to misconfiguration in one of these areas:

  • Origin Access Identity (OAI) not properly set up
  • Incorrect S3 bucket policy
  • Bucket permissions not allowing CloudFront access
  • Missing or incorrect CORS configuration

1. Verify Your Origin Access Identity

First, ensure you've created an Origin Access Identity in CloudFront and associated it with your distribution:

// Example AWS CLI command to create OAI
aws cloudfront create-cloud-front-origin-access-identity \
    --cloud-front-origin-access-identity-config \
    CallerReference="unique-string",Comment="Access identity for S3 bucket"

2. Update Your S3 Bucket Policy

Your bucket policy should explicitly grant access to the CloudFront OAI. Here's a corrected version:

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "1",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity E1A2B3C4D5E6F7"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::your-bucket-name/*"
        }
    ]
}

3. Check Your CloudFront Distribution Settings

In your CloudFront distribution:

  • Ensure "Restrict Bucket Access" is set to "Yes"
  • Select the correct OAI from the dropdown
  • Set "Grant Read Permissions on Bucket" to "Yes, Update Bucket Policy"

4. Verify Object Ownership

If you're using S3 buckets with ACLs disabled (recommended), ensure the bucket owner has full control:

aws s3api put-bucket-ownership-controls \
    --bucket your-bucket-name \
    --ownership-controls Rules=[{ObjectOwnership="BucketOwnerEnforced"}]
  • Use AWS CLI to verify permissions: aws s3api get-bucket-policy --bucket your-bucket-name
  • Check CloudFront logs for detailed error information
  • Clear CloudFront cache after making changes
  • Test with a simple text file before moving to complex content

For more complex setups requiring CORS:

// Example CORS configuration for S3 bucket
[
    {
        "AllowedHeaders": ["*"],
        "AllowedMethods": ["GET", "HEAD"],
        "AllowedOrigins": ["https://your-cloudfront-domain.cloudfront.net"],
        "ExposeHeaders": []
    }
]