Skip to content

Instantly share code, notes, and snippets.

@iinfin
Created February 10, 2022 19:45
Show Gist options
  • Save iinfin/e947ac60eef6de5598a6fb7ffdb9f977 to your computer and use it in GitHub Desktop.
Save iinfin/e947ac60eef6de5598a6fb7ffdb9f977 to your computer and use it in GitHub Desktop.
cloudflare password protection per site using values from KV
const _REALM = 'Secure Area';
const _DEFAULT_USERNAME = 'username';
const _DEFAULT_PASSWORD = null;
addEventListener('fetch', (event) => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
const password = await getValidCredentials(request);
return createResponse(request, password);
}
// #################################################################################################
/**
* Get password from Cloudflare KV
* project-name from url to be used as key
* https://developers.cloudflare.com/workers/runtime-apis/kv#reading-key-value-pairs
* @returns {string}
*/
async function getValidCredentials(request) {
const name = new URL(request.url).host.split('.')[0];
const password = await SECURE.get(name);
return password || _DEFAULT_PASSWORD;
}
// #################################################################################################
/**
* Either accept or deny access, create Response
* @param {Request} request
* @param {string} password
* @returns {Response}
*/
async function createResponse(request, password) {
if (password === null) {
// password is not set
const response = await fetch(request);
return response;
} else {
// security check
const authorization = request.headers.get('authorization');
if (!request.headers.has('authorization')) {
return getUnauthorizedResponse('Provide User Name and Password to access this page.');
}
const credentials = parseCredentials(authorization);
if (credentials[0] !== _DEFAULT_USERNAME || credentials[1] !== password) {
return getUnauthorizedResponse('The User Name and Password combination you have entered is invalid.');
}
const response = await fetch(request);
return response;
}
}
// #################################################################################################
/**
* Break down base64 encoded authorization string into plain-text username and password
* @param {string} authorization
* @returns {string[]}
*/
function parseCredentials(authorization) {
const parts = authorization.split(' ');
const plainAuth = atob(parts[1]);
const credentials = plainAuth.split(':');
return credentials;
}
/**
* Helper funtion to generate Response object
* @param {string} message
* @returns {Response}
*/
function getUnauthorizedResponse(message) {
let response = new Response(message, {
status: 401,
});
response.headers.set('WWW-Authenticate', `Basic realm="${_REALM}"`);
return response;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment