-
-
Save jeroenvollenbrock/94edbbc62adc986d6d6a9a3076e66f5b to your computer and use it in GitHub Desktop.
var USERS = { | |
protecteddir: [{ | |
username: 'user', | |
password: 'pass', | |
}], | |
}; | |
//Response when auth is not valid. | |
var response401 = { | |
statusCode: 401, | |
statusDescription: 'Unauthorized', | |
headers: { | |
'www-authenticate': {value:'Basic'}, | |
}, | |
}; | |
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; | |
function btoa(input) { | |
input = String(input); | |
var bitmap, a, b, c, | |
result = "", i = 0, | |
rest = input.length % 3; // To determine the final padding | |
for (; i < input.length;) { | |
if ((a = input.charCodeAt(i++)) > 255 | |
|| (b = input.charCodeAt(i++)) > 255 | |
|| (c = input.charCodeAt(i++)) > 255) | |
throw new TypeError("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range."); | |
bitmap = (a << 16) | (b << 8) | c; | |
result += b64.charAt(bitmap >> 18 & 63) + b64.charAt(bitmap >> 12 & 63) | |
+ b64.charAt(bitmap >> 6 & 63) + b64.charAt(bitmap & 63); | |
} | |
// If there's need of padding, replace the last 'A's with equal signs | |
return rest ? result.slice(0, rest - 3) + "===".substring(rest) : result; | |
} | |
function handler(event) { | |
var request = event.request; | |
var headers = request.headers; | |
var auth = request.headers.authorization && request.headers.authorization.value; | |
var project = request.uri.substring(1).split(/\.|\//)[0]; | |
var users = USERS[project]; | |
if(users) { | |
if(!auth || !auth.startsWith('Basic ')) { | |
return response401; | |
} | |
if(!users.find(function(user) { | |
// Construct the Basic Auth string | |
var authString = 'Basic ' + btoa(user.username + ':' + user.password); | |
return authString === auth; | |
})) { | |
return response401; | |
} | |
} | |
return request; | |
} |
Thank you so much for your support, It's working for me now !!!
yw!
Thanks for this!
I adapted it slightly because I wanted a single user for the whole site.
Coworker @aalin also simplified it a little.
We set it up per @lehuy2012's comment above: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/functions-tutorial.html
Edited 2022-10-02 to handle ":" in passwords per comments below.
// Source: https://gist.github.com/jeroenvollenbrock/94edbbc62adc986d6d6a9a3076e66f5b
var USERNAME = 'myuser';
var PASSWORD = 'mypassword';
var response401 = {
statusCode: 401,
statusDescription: 'Unauthorized',
headers: {
'www-authenticate': {value:'Basic'},
},
};
function validateBasicAuth(authHeader) {
var match = authHeader.match(/^Basic (.+)$/);
if (!match) return false;
var credentials = String.bytesFrom(match[1], 'base64').split(':', 2);
return credentials[0] === USERNAME && credentials[1] === PASSWORD;
}
function handler(event) {
var request = event.request;
var headers = request.headers;
var auth = (headers.authorization && headers.authorization.value) || '';
if (!validateBasicAuth(auth)) return response401;
return request;
}
@henrik does your example hold up if the password itself contains :
?
@rashidnhm: It seems like it doesn't.
It should only split the credentials into two parts. This should work with passwords containing :
.
var credentials = String.bytesFrom(match[1], 'base64').split(':', 2);
Thanks @rashidnhm – good catch! And thanks @aalin :)
I've edited my comment above to incorporate @aalin's fix for ease of copy-pasting.
And to make it explicit – we only need to handle ":" in passwords, not in usernames. They're not allowed in usernames.
Using the function above generated the following error:
The CloudFront function associated with the CloudFront distribution is invalid or could not run. SyntaxError: String.bytesFrom() is deprecated, please use another method Buffer.from()
This is the adjustment which made it work:
const credentials = Buffer.from(match[1], 'base64').toString('utf-8').split(':', 2);
Sure! I modified it somewhat to fit our purposes, but this works:
Cloudformation stack for the function:
Then how I clicked it into a cloudfront distribution: