Hosting a Private Static Website on Amazon S3

Tuesday, 3 November 2020

S3 is a good choice to host static websites, especially behind CloudFront:

Setting this up is fairly straightforward (and well-documented):

There isn’t really a well-defined way to serve private static websites this way, though. Luckily, Cloudfront features a version of Amazon Lambda named Lambda@Edge that allows you to execute code at CDN edge locations to reduce latency.

Crucially, you can intercept an incoming request and mutate it in some way before it propagates “behind” Cloudfront to the S3 bucket. While this is probably not the intended use case for Lambda@Edge, this is perfect for our needs. A rudimentary form of this might use Basic Auth, but I’d really like to use OAuth instead. Luckily, this GitHub project does exactly this: Widen/cloudfront-auth.

With a Lambda@Edge function acting as an auth layer, the system now looks like this:

First, set up a new S3 bucket, ensuring that all public access is disabled:

Importantly, (once the bucket is created) make sure that the Static website hosting setting is disabled; we want all incoming requests to be routed through Cloudfront, and enabling Static website hosting will allow direct HTTP requests to the bucket.

Next, create the Lambda function:

  1. Follow the instructions at to create a ZIP file containing the Lambda function’s payload; you’ll need to pick an OAuth provider first.
  2. Follow the instructions at to create a Lambda function with this ZIP file.

Finally, create the Cloudfront distribution. Set the origin to the S3 bucket, and ensure that Restrict Bucket Access is enabled.

Set a Lambda Function Association, linking the Viewer Request event to your Lambda function.

Wait for the distribution to be deployed, and your static website should now be accessible behind an OAuth login.