Skip to content

Instantly share code, notes, and snippets.

Embed
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);
};
@iamwalker
Copy link

iamwalker commented Apr 24, 2018

Is there a way to set this up on specific directories in the s3 bucket? i.e. domain.com allowed, domain.com/dir triggers auth

Copy link

ghost commented Jun 13, 2018

@iamwalker In CloudFront, under "Origin Settings", you can set the Origin Path. For example, I'm running an S3 bucket with dev, stage and prod folders. I have one CloudFront distribution for each one.

@mathieug
Copy link

mathieug commented Jul 2, 2018

You should return the callback or wrap the second call to it into a else case.

@Spaideri
Copy link

Spaideri commented Nov 15, 2018

Hi!

Inspired from this I made my own version which is using a shared cookie secret to allow application to use Authorization header for JWT Bearer tokens. See webscale-oy/aws-cloudfront-basic-auth for Cloudformation templates and documentation.

@BenPortner
Copy link

BenPortner commented Mar 18, 2020

Super helpful. Thank you very much!

@ivictbor
Copy link

ivictbor commented Jun 11, 2020

@sreejithps303
Copy link

sreejithps303 commented Aug 17, 2020

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

@iothack
Copy link

iothack commented Sep 11, 2020

@SunnyVZ777
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?

@rkz
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.

@nachmore
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.

@rkz
Copy link

rkz commented Sep 29, 2020

@nachmore that was it :) Thank you

@Habbie
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=.

@jeroenvollenbrock
Copy link

jeroenvollenbrock commented May 15, 2021

This is now also possible, cheaper and faster with the newly launched CloudFront Functions (https://gist.github.com/jeroenvollenbrock/94edbbc62adc986d6d6a9a3076e66f5b)

@malcolmm83
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