DEV Community

4 2 2 2 2

Common Mistakes When Accessing Files from a Custom URL Using CloudFront and S3

Working with Amazon CloudFront and S3 is a popular and powerful combo when it comes to hosting static files, configuring custom URLs, or enabling features like Apple Universal Links (via apple-app-site-association). But it's also easy to make configuration mistakes that can cause frustrating errors like "Access Denied" or "NoSuchKey".

In this post, I’ll walk you through one of the most common mistakes, one that I recently ran into myself and how to fix it quickly.


❌ The Problem: “Access Denied” or 404 from CloudFront

access denied

Let’s say you want to serve a file like:

https://your-cloudfront-url/.well-known/apple-app-site-association
Enter fullscreen mode Exit fullscreen mode

You upload the file with name apple-app-site-association, to your S3 bucket and configure a CloudFront distribution. In the process, you set:

  • Origin Domain: your-bucket.s3.region.amazonaws.com
  • Origin Path: /.well-known/apple-app-site-association

Everything seems perfect, but when you try to access the file through CloudFront, you get:

AccessDenied
Enter fullscreen mode Exit fullscreen mode

or

The specified key does not exist.
Enter fullscreen mode Exit fullscreen mode

🔍 What Went Wrong

Here’s the key misunderstanding:

The Origin Path in CloudFront is not the full file path, it’s a prefix that's automatically added to every request path.

So, if your CloudFront request is for:

/.well-known/apple-app-site-association
Enter fullscreen mode Exit fullscreen mode

And your origin path is also set to:

/.well-known/apple-app-site-association
Enter fullscreen mode Exit fullscreen mode

Then CloudFront tries to fetch:

S3: /.well-known/apple-app-site-association/.well-known/apple-app-site-association
Enter fullscreen mode Exit fullscreen mode

Which obviously doesn’t exist — hence the error.


✅ The Correct Setup

Here’s how to fix and simplify things:

Remove the Origin Path from your CloudFront origin settings.

✅ In your S3 bucket:

  • Create a folder called .well-known
  • Upload your file inside that folder:

     .well-known/apple-app-site-association
    

s3 folder structure

✅ Make sure CloudFront has access (via Origin Access Control).

origin access control

✅ Leave Origin path - optional as empty

Secure Bucket Policy for CloudFront OAC:
Add this to your bucket policy (replace ACCOUNT_ID and DISTRIBUTION_ID):

   {
     "Version": "2012-10-17",
     "Statement": [
       {
         "Sid": "AllowCloudFrontAccessViaOAC",
         "Effect": "Allow",
         "Principal": {
           "Service": "cloudfront.amazonaws.com"
         },
         "Action": "s3:GetObject",
         "Resource": "arn:aws:s3:::your-bucket-name/*",
         "Condition": {
           "StringEquals": {
             "AWS:SourceArn": "arn:aws:cloudfront::ACCOUNT_ID:distribution/DISTRIBUTION_ID"
           }
         }
       }
     ]
   }
Enter fullscreen mode Exit fullscreen mode

✅ Make sure your bucket has public access disabled

s3 public access disabled

✅ Now, test the file at:

https://your-cloudfront-url/.well-known/apple-app-site-association
Enter fullscreen mode Exit fullscreen mode

🎉 It should work!


🧠 Takeaway

When working with CloudFront and S3:

  • Keep the Origin Path empty unless you really need it.
  • Structure your S3 folders to match your desired URL path.
  • CloudFront appends the request path to the origin path, so watch out for unnecessary nesting.

🔄 Bonus Tip: Content-Type for apple-app-site-association

If you’re hosting apple-app-site-association, don’t forget to set the correct Content-Type in S3:

application/json
Enter fullscreen mode Exit fullscreen mode

Even though the file doesn’t have a .json extension, Apple expects it to have the correct Content-Type header.


Hope this helps you avoid the same mistake and get your setup running smoothly.

If this saved you hours of debugging, you’re not alone 😄

Let me know in the comments if you’ve run into other CloudFront/S3 gotchas!

Top comments (0)