Authentication at the Edge with Lambda@Edge
One of the trickier parts of this site is protecting the photo gallery. The site is fully static — there’s no server to check credentials against. So the authentication has to happen at the CDN level.
The Setup
The solution uses three AWS services working together:
- Cognito — manages the user pool and handles Google OAuth
- CloudFront — serves the site and routes requests
- Lambda@Edge — runs on every request to protected paths and checks for a valid JWT
How It Works
When someone requests a gallery image, the request hits CloudFront first. Before CloudFront fetches the image from S3, it triggers a Lambda@Edge function on the viewer-request event:
exports.handler = async function(event) {
const request = event.Records[0].cf.request;
const cookies = parseCookies(request.headers);
const token = cookies['id_token'];
if (!token) {
return redirectToLogin(request);
}
try {
await verifyToken(token);
return request; // allow through
} catch (err) {
return redirectToLogin(request);
}
};
The function checks for an id_token cookie, validates it against Cognito’s JWKS endpoint, and either lets the request through or redirects to the login page.
The Cost Question
Lambda@Edge charges per request. For a personal site with a handful of users, it’s essentially free. But if bots start hammering your endpoints, it could add up. I keep a budget alarm set at $5/month and have a documented procedure for pulling the Lambda@Edge association if things go sideways.
Lessons Learned
- Lambda@Edge functions must be deployed to
us-east-1, regardless of where your other infrastructure lives - You need to publish a numbered version —
$LATESTwon’t work - Propagation to all edge locations takes 5-15 minutes after any change