Some websites require basic common authentication to protect private data. If website is running on the server, its not much difficult to add authentication. But when it comes to serverless like S3, creating an authentication layer is a bit complicated.
This blog will show how to protect static website on s3, using Lambda and Cloudfront.
Create a static file site on S3.
- Create a sample HTML file named index.html
- Create an S3 bucket with a unique name.
- After giving the bucket name, click on next, till you reach Set permissions
- On Set, Permissions tab unchecks Block all public access.
- Click on next and then click on create a bucket.
Enabling S3 for a website.
- Click on the bucket you have just created.
- Upload index.html page and make it public.
- Go to the properties tab and click on Static Website hosting.
- Click on Use this bucket to host a website and in index document field enter HTML
- Save it and copy the Website endpoint.
- Now you can copy and paste the endpoint in a browser and you will be able to see the website page.
Configuring Cloudfront for S3 website
- Go to Cloudfront and Click on Create Distribution.
- Under Web, Section click on Get Started.
- On Create Distribution windows, in Origin Domain name, search for your bucket and select.
- Select “Yes” for Restrict Bucket Access and under Origin Access Identity click on Create new Identity.
- For Grant Read Permissions on Bucket, click on Yes, Update Bucket Policy.
- Scroll down to Default Root Object and type HTML.
- Click on create distribution and it will take around 15 min to get deployed.
Creating a Lambda function for Authentication.
Now we have to configure the actual logic that will handle the Authentication.
- Go to Lambda and Create a function.
- Scroll down to function code and paste the following code into the window and click on save.
exports.handler = (event, context, callback) => {
// Get the request and its headers
const request = event.Records[0].cf.request;
const headers = request.headers;
// Specify the username and password to be used
const user = \'user\';
const pw = \'password\';
// Build a Basic Authentication string
const authString = \'Basic \' + new Buffer(user + \':\' + pw).toString(\'base64\');
// Challenge for auth if auth credentials are absent or incorrect
if (typeof headers.authorization == \'undefined\' || headers.authorization[0].value != authString) {
const response = {
status: \'401\',
statusDescription: \'Unauthorized\',
body: \'Unauthorized\',
headers: {
\'www-authenticate\': [{key: \'WWW-Authenticate\', value:\'Basic\'}]
},
};
callback(null, response);
}
// User has authenticated
callback(null, request);
};
3. Scroll up to top and click on Add triggers. Select Cloudfront from the drop-down list and click on Deploy to Lambda@Edge
4. Select your cloudfront distribution ID and under Cloudfront event select Viewer request.
5. Confirm deploy to Lambda@Edge by checking the box and click on deploy.
Now we are all ready to test the S3 website authentication.
Copy the domain of the cloudfront and paste it in browser. It will ask you for authentication. Based on the above code the credentials are “user” and “password”
Using above solution, you can leverage lambda to provide authentication to the static website that is hosted on S3. It could be very useful where you want to restrict the website accessibility.
Written by – Atin Mittal