This guide explains how to implement user authentication for a static website hosted on Amazon S3, served through CloudFront, using a Lambda@Edge function. The Lambda function validates user credentials against a DynamoDB table, securing access to the site. While API Gateway can be integrated for API-based authentication, this project focuses on securing a static S3 site with CloudFront and Lambda@Edge.
import base64
import boto3
import os
from boto3.dynamodb.conditions import Key
dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
table = dynamodb.Table('Users')
def lambda_handler(event, context):
if os.getenv('LAMBDA_ENABLED', 'true').lower() != 'true':
return {
'status': '403',
'statusDescription': 'Forbidden',
'body': 'The service is currently disabled.'
}
request = event['Records'][0]['cf']['request']
headers = request['headers']
if 'authorization' in headers:
try:
auth_header = headers['authorization'][0]['value']
encoded_credentials = auth_header.split(' ')[1]
decoded_credentials = base64.b64decode(encoded_credentials).decode('utf-8')
username, password = decoded_credentials.split(':')
response = table.get_item(Key={'user_id': username})
if 'Item' not in response:
return unauthorized_response()
user = response['Item']
if password == user['password']:
return request
except Exception as e:
print(f"[ERROR] Auth failed: {e}")
return unauthorized_response()
def unauthorized_response():
return {
'status': '401',
'statusDescription': 'Unauthorized',
'headers': {
'www-authenticate': [{'key': 'WWW-Authenticate', 'value': 'Basic'}]
}
}
{"user_id": "test@email.com", "password": "password@123"}).The S3-hosted static website was successfully secured with user authentication using Lambda@Edge and CloudFront. Users must now provide valid credentials (stored in DynamoDB) to access the site, with the process fully integrated and functional.