Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Basic HTTP Authentication for CloudFront with Lambda@Edge
'use strict';
exports.handler = (event, context, callback) => {
// Get request and request headers
const request = event.Records[0].cf.request;
const headers = request.headers;
// Configure authentication
const authUser = 'user';
const authPass = 'pass';
// Construct the Basic Auth string
const authString = 'Basic ' + new Buffer(authUser + ':' + authPass).toString('base64');
// Require Basic authentication
if (typeof headers.authorization == 'undefined' || headers.authorization[0].value != authString) {
const body = 'Unauthorized';
const response = {
status: '401',
statusDescription: 'Unauthorized',
body: body,
headers: {
'www-authenticate': [{key: 'WWW-Authenticate', value:'Basic'}]
callback(null, response);
// Continue request processing if authentication passed
callback(null, request);
Copy link

BenPortner commented Mar 18, 2020

Super helpful. Thank you very much!

Copy link

ivictbor commented Jun 11, 2020

Copy link

sreejithps303 commented Aug 17, 2020

Can we pick the credentials from secret manager? can anyone help with the code?

Copy link

iothack commented Sep 11, 2020

Copy link

SunnyVZ777 commented Sep 21, 2020

Do anyone get a problem that in phone (ios) it just popup password panel serveral times when loading the website?

Copy link

rkz commented Sep 28, 2020

Similar problem here.

It seems the Authorization header is no longer read by Lambda or some other part of the chain?

I replaced line 17 with:

const body = 'Unauthorized, headers are ' + JSON.stringify(headers);

Test case (with some sensitive data replaced by [...]):

$ curl --user xxx:yyy https://my_endpoint
> GET / HTTP/2
> Host: [...]
> Authorization: Basic eHh4Onl5eQ==
< HTTP/2 401
< content-length: 341
< server: CloudFront
< date: Mon, 28 Sep 2020 16:40:50 GMT
* Authentication problem. Ignoring this.
< www-authenticate: Basic

Unauthorized, headers is {"host":[{"key":"Host","value":"[...]"}],"x-forwarded-for":[{"key":"X-Forwarded-For","value":"[...]"}],"user-agent":[{"key":"User-Agent","value":"Amazon CloudFront"}],"via":[{"key":"Via","value":"[...]"}]}* Closing connection 0

The headers variable has no key authorization.

Copy link

nachmore commented Sep 29, 2020

@rkz - make sure that your trigger CloudFront Event is Viewer Request and not Origin Request. The auth headers are stripped out of Origin.

Copy link

rkz commented Sep 29, 2020

@nachmore that was it :) Thank you

Copy link

Habbie commented Dec 15, 2020

Line 23 is broken - the realm parameter is mandatory! This is documented in RFC7617 section 2 and I found out because Python's urllib's AuthHandler classes do not recognise the header without realm=.

Copy link

jeroenvollenbrock commented May 15, 2021

This is now also possible, cheaper and faster with the newly launched CloudFront Functions (

Copy link

malcolmm83 commented Apr 13, 2022

@rkz - make sure that your trigger CloudFront Event is Viewer Request and not Origin Request. The auth headers are stripped out of Origin.

I added the 'Authorization' header to the cache key and it now comes through to the 'Origin Request'. My issue is that I need both this header as well as the origin domain for my lambda, and I can't determine the domain from the 'Viewer Request' . Wish this stuff was documented better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment