DEV Community

se-piyush
se-piyush

Posted on • Edited on

How to Resolve 403 Access Issues When Deploying a SPA on AWS with S3 and CloudFront

When deploying a Vue.js Single Page Application (SPA) on AWS, developers often encounter a common issue: the 403 access error. This typically happens when refreshing a page or accessing a non-root URL after the application has already loaded. Here’s my experience troubleshooting and resolving this issue using S3 for static website hosting and CloudFront for distribution.

The Problem: 403 Access Error After Refreshing Routes

While working on deploying my Vue.js application on AWS, I stored the bundled JavaScript files in a S3 bucket and used it for static website hosting. I then created a CloudFront distribution and linked it to my S3 bucket.

The default route pointed to the index.html page, where my app was bootstrapped. Everything worked well when loading the app using the CloudFront domain. However, once the app was loaded, a path would be appended to the domain, like cloud-domain.com/dashboard.

The problem occurred when I refreshed the /dashboard route or navigated to another path directly—it returned a 403 Access Denied error.

403 Access Error Example

Why It Happened: CloudFront's Path Request Mechanism

Here’s how CloudFront works: when you request a URL with a path, CloudFront treats it as a request for a specific file or object. It checks whether the file exists in its cache or in the linked S3 bucket. In this case, since my S3 bucket didn’t contain an actual dashboard file (or any other path-specific file), CloudFront returned the 403 error.

The Solution: Redirect All Requests to index.html

The solution to this issue is straightforward: I needed to redirect all requests to index.html, as my Vue.js app handles routing internally. After some research, I discovered that I needed to update configurations in both my S3 bucket and CloudFront distribution.

Here’s what I did:

Step 1: Update S3 Bucket Settings

In the S3 bucket, under the Static Website Hosting section, I had already set index.html as the default document. However, I also needed to set index.html as the Error Document. This way, when any request came in that didn’t match an existing file (like /dashboard), it would return index.html instead of throwing a 403 error.

Here’s how the S3 settings looked after I made the change:

S3 Static Website Hosting Settings

S3 Error Document Settings

Step 2: Configure CloudFront Custom Error Responses

Next, I needed to configure my CloudFront distribution to handle these requests properly. In the Error Pages section of CloudFront, I created a custom error response for 403 errors.

  • I set the response code to 200 (OK).
  • I specified /index.html as the page to serve in the case of a 403 error.
  • This ensured that when CloudFront couldn’t find the requested path (like /dashboard), it would serve the index.html file instead.

Here’s how I configured CloudFront:

Image description

CloudFront Error Pages Settings

Final Configuration in CloudFront:

Image description

After configuring these settings, the issue was resolved. Now, any request to a specific path is properly redirected to the index.html page, allowing Vue.js to handle the routing internally.

Voila! Issue Resolved

By making these two key changes—updating the S3 error document settings and configuring CloudFront's custom error responses—the 403 error was eliminated. Now, my application routes work perfectly, even when refreshing or navigating directly to different URLs.

Conclusion

Deploying a Vue.js Single Page Application on AWS using S3 and CloudFront can result in 403 errors when refreshing or navigating to non-root URLs. However, by redirecting all paths to the index.html page, you allow Vue.js to manage routing internally, solving the issue.

Top comments (0)