Ongoing service disruptions
For the most recent update on ongoing service disruptions affecting the AWS Middle East (UAE) Region (ME-CENTRAL-1), refer to the AWS Health Dashboard. For information on AWS Service migration, see How do I migrate my services to another region?
Why do I get "403 Access Denied" errors when I use an S3 REST API endpoint as the origin of my CloudFront distribution?
I want to troubleshoot "403 Access Denied" errors that Amazon CloudFront returns from Amazon Simple Storage Service (Amazon S3).
Short description
To avoid "Access Denied" errors, use the following configurations:
- Make the S3 objects publicly accessible.
- Use origin access control (OAC) for S3 buckets that contain objects that are server-side encrypted with AWS Key Management Service (AWS KMS).
Note: You must use OAC instead of origin access identity (OAI). because OAI doesn't serve AWS KMS encrypted objects. - Modify the S3 bucket policy so that it allows access to s3:GetObject.
- Make sure that the AWS account that owns the S3 bucket also owns the object.
- Confirm that the requested objects exist in the S3 bucket.
- Define a default root object so that clients can request the root of your distribution.
- For an OAI configuration, you must include the OAI in the S3 bucket policy. For an OAC configuration, you must include the CloudFront service principal in the S3 bucket policy.
Resolution
Note: If you receive errors when you run AWS Command Line Interface (AWS CLI) commands, then see Troubleshooting errors for the AWS CLI. Also, make sure that you're using the most recent AWS CLI version.
Make the S3 objects publicly accessible
To determine if the objects in your S3 bucket are publicly accessible, open the S3 object's URL in a web browser. Or, run a curl command on the URL.
The following is an example URL of an S3 object:
https://DOC-EXAMPLE-BUCKET.s3.amazonaws.com/index.html
If either the web browser or curl command returns an "Access Denied" error, then the object isn't publicly accessible.
To make the object publicly accessible, take one of the following actions:
- Create a bucket policy that grants read-only permissions for the bucket.
- Use the S3 console to allow public read access for the object.
- Use the REST API endpoint to configure either OAC or OAI for the distribution.
- Use AWS Signature Version 4 to authenticate requests to S3.
Use OAC for objects that are AWS KMS encrypted
To use OAC, add a statement to the AWS KMS key policy that grants the CloudFront service principal permission to use the key. You can also use Lambda@Edge instead of OAC. For more information, see Serving SSE-KMS encrypted content from S3 using CloudFront.
To confirm that you encrypted your object with AWS KMS, take one of the following actions:
- Use the S3 console to view the properties of the object. Review the Encryption dialog box. If AWS KMS is selected, then the object is AWS KMS encrypted.
- Run the head-object command. If the command returns ServerSideEncryption as aws:kms, then the object is AWS KMS encrypted.
Allow access to s3:GetObject
Even if you have an explicit Allow statement for s3:GetObject in your bucket policy, confirm that there's no conflict with an explicit Deny statement. An explicit Deny statement overrides an explicit Allow statement. For more information about Deny and Allow statements, see Policy evaluation logic.
To confirm that your bucket policy allows s3:GetObject and no explicit Deny statements, complete the following steps:
-
Open the Amazon S3 console.
-
Select your bucket.
-
Choose the Permissions tab.
-
Choose Bucket policy.
-
Check for statements with "Action": "s3:GetObject" or "Action": "s3:*".
The following example policy includes Allow statements that grant CloudFront OAC and CloudFront OAI access to s3:GetObject. It also includes an Allow statement that grants public access to s3:GetObject. However, there's an explicit Deny statement for s3:GetObject that blocks access unless the request is from a specific Amazon Virtual Private Cloud (Amazon VPC).{ "Version": "2012-10-17", "Id": "PolicyForCloudFrontPrivateContent", "Statement": [{ "Sid": "Allow-OAC-Access-To-Bucket", "Effect": "Allow", "Principal": { "Service": "cloudfront.amazonaws.com" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*", "Condition": { "StringEquals": { "AWS:SourceArn": "arn:aws:cloudfront::111122223333:distribution/EDFDVBD6EXAMPLE" } } }, { "Sid": "Allow-OAI-Access-To-Bucket", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity EAF5XXXXXXXXX" }, "Action": "s3:GetObject", "Resource": [ "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*" ] }, { "Sid": "Allow-Public-Access-To-Bucket", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": [ "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*" ] }, { "Sid": "Access-to-specific-VPCE-only", "Effect": "Deny", "Principal": "*", "Action": "s3:GetObject", "Resource": [ "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*" ], "Condition": { "StringNotEquals": { "aws:sourceVpce": "vpce-1a2b3c4d" } } } ] } -
Modify the bucket policy to remove or edit statements that block CloudFront OAI, CloudFront OAC, or public access to s3:GetObject.
Note: CloudFront caches the results of an "Access Denied" error for up to 5 minutes. After you remove a Deny statement from the bucket policy, you can run an invalidation on your distribution to remove the object from the cache.
Grant ownership of S3 buckets and objects
Verify that the account of the AWS Identity and Access Management (IAM) identity that created the bucket or object owns the bucket or object.
Note: The object-ownership requirement applies only to access that a bucket policy grants. It doesn't apply to access that the object's access control list (ACL) grants.
To check whether the bucket and objects have the same owner, complete the following steps:
-
Run the list-buckets command to get the S3 canonical ID of the bucket owner:
aws s3api list-buckets --query Owner.ID -
Run the list-objects command to get the S3 canonical ID of the object owner:
aws s3api list-objects --bucket DOC-EXAMPLE-BUCKET --prefix index.htmlNote: The preceding example command shows a single object, but you can run the list-objects command to check several objects.
If the canonical IDs don't match, then the bucket and object have different owners.
Note: You can also use the Amazon S3 console to check the bucket and object owners. You can find the owners on the Permissions tab of the bucket or object.
To change the object's owner to the bucket owner, complete the following steps:
-
From the object owner's account, run the get-object-acl command to retrieve the ACL permissions:
aws s3api get-object-acl --bucket DOC-EXAMPLE-BUCKET --key object-name -
If the object has bucket-owner-full-control ACL permissions, then proceed to step 3. If the object doesn't have bucket-owner-full-control ACL permissions, then run the put-object-acl command from the object owner's account:
aws s3api put-object-acl --bucket DOC-EXAMPLE-BUCKET --key object-name --acl bucket-owner-full-control -
From the bucket owner's account, run the following command to copy the object over itself and change the owner of the object:
aws s3 cp s3://DOC-EXAMPLE-BUCKET/index.html s3://DOC-EXAMPLE-BUCKET/index.html --storage-class STANDARDNote: Replace --storage-class with your storage class.
Move the objects to the bucket
To check whether an object exists in the bucket, run the head-object command.
Note: S3 object names are case-sensitive. Confirm that the object request that's sent to CloudFront matches the S3 object name. If the request doesn't have the correct object name, then Amazon S3 responds as though the object is missing. To identify the object that CloudFront requests from Amazon S3, use server access logging.
If the object exists in the bucket, then the "Access Denied" error doesn't mask a "404 Not Found" error. Check other configuration requirements to resolve the "Access Denied" error.
If the object isn't in the bucket, then the "Access Denied" error masks a "404 Not Found" error. You must resolve the issue that's related to the missing object.
Define a default root object
To define a default root object, see Specify a default root object.
Note: It's a security best practice to deny public s3:ListBucket access. If you allow public s3:ListBucket access, then users can see and list all objects in a bucket. This exposes object metadata details, such as key and size, to all users.
Add OAI or CloudFront service principal permissions in the S3 bucket policy
To check whether your bucket policy allows OAI, open the Amazon S3 console. Find your bucket, and then on the Permissions tab, choose Bucket policy.
The following example policy includes an Allow statement for the CloudFront service principal when you configure OAC:
{ "Sid": "Allow-OAC-Access-To-Bucket", "Effect": "Allow", "Principal": { "Service": "cloudfront.amazonaws.com" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*", "Condition": { "StringEquals": { "AWS:SourceArn": "arn:aws:cloudfront::111122223333:distribution/EDFDVBD6EXAMPLE" } } }
The following example policy includes an Allow statement for OAI:
{ "Sid": "1", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity EAF5XXXXXXXXX" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*" }
To update your bucket policy on the CloudFront console, complete the following steps:
- Open the CloudFront console.
- Select your distribution.
- Choose the Origins and Origin Groups tab.
- Select the S3 origin, and then choose Edit.
- For Restrict Bucket Access, choose Yes.
- For Origin Access Identity, choose an existing identity or create a new one.
- For Grant read permissions on bucket, choose Yes, update bucket policy.
- Choose Yes, edit.
Related information
Troubleshooting error response status codes in CloudFront
How do I troubleshoot 403 Access Denied errors from Amazon S3?
- Language
- English
Related videos


If you're working with an SPA, it's very possible you don't need to solve these errors: all you need to do is handle them appropriately so your SPA's internal routing takes over.
This is kind of alluded to by the "requested objects must exist" suggestion here, but it's hard to realize this is your problem if, when you check S3, all of the SPA's resources are right there!
Thank you for your comment. We'll review and update the Knowledge Center article as needed.
Relevant content
- Accepted Answerasked a year ago
- asked 9 months ago
AWS OFFICIALUpdated 4 months ago