mirror of
https://github.com/Gerald-Ha/HodlEye-Crypto-Price-Tracker.git
synced 2025-06-25 17:16:27 +00:00
99 lines
3.1 KiB
JavaScript
99 lines
3.1 KiB
JavaScript
const auth = require('basic-auth')
|
|
const assert = require('assert')
|
|
const timingSafeEqual = require('crypto').timingSafeEqual
|
|
|
|
// Credits for the actual algorithm go to github/@Bruce17
|
|
// Thanks to github/@hraban for making me implement this
|
|
function safeCompare(userInput, secret) {
|
|
const userInputLength = Buffer.byteLength(userInput)
|
|
const secretLength = Buffer.byteLength(secret)
|
|
|
|
const userInputBuffer = Buffer.alloc(userInputLength, 0, 'utf8')
|
|
userInputBuffer.write(userInput)
|
|
const secretBuffer = Buffer.alloc(userInputLength, 0, 'utf8')
|
|
secretBuffer.write(secret)
|
|
|
|
return !!(timingSafeEqual(userInputBuffer, secretBuffer) & userInputLength === secretLength)
|
|
}
|
|
|
|
function ensureFunction(option, defaultValue) {
|
|
if(option == undefined)
|
|
return function() { return defaultValue }
|
|
|
|
if(typeof option != 'function')
|
|
return function() { return option }
|
|
|
|
return option
|
|
}
|
|
|
|
function buildMiddleware(options) {
|
|
var challenge = options.challenge != undefined ? !!options.challenge : false
|
|
var users = options.users || {}
|
|
var authorizer = options.authorizer || staticUsersAuthorizer
|
|
var isAsync = options.authorizeAsync != undefined ? !!options.authorizeAsync : false
|
|
var getResponseBody = ensureFunction(options.unauthorizedResponse, '')
|
|
var realm = ensureFunction(options.realm)
|
|
|
|
assert(typeof users == 'object', 'Expected an object for the basic auth users, found ' + typeof users + ' instead')
|
|
assert(typeof authorizer == 'function', 'Expected a function for the basic auth authorizer, found ' + typeof authorizer + ' instead')
|
|
|
|
function staticUsersAuthorizer(username, password) {
|
|
for(var i in users)
|
|
if(safeCompare(username, i) & safeCompare(password, users[i]))
|
|
return true
|
|
|
|
return false
|
|
}
|
|
|
|
return function authMiddleware(req, res, next) {
|
|
var authentication = auth(req)
|
|
|
|
if(!authentication)
|
|
return unauthorized()
|
|
|
|
req.auth = {
|
|
user: authentication.name,
|
|
password: authentication.pass
|
|
}
|
|
|
|
if(isAsync)
|
|
return authorizer(authentication.name, authentication.pass, authorizerCallback)
|
|
else if(!authorizer(authentication.name, authentication.pass))
|
|
return unauthorized()
|
|
|
|
return next()
|
|
|
|
function unauthorized() {
|
|
if(challenge) {
|
|
var challengeString = 'Basic'
|
|
var realmName = realm(req)
|
|
|
|
if(realmName)
|
|
challengeString += ' realm="' + realmName + '"'
|
|
|
|
res.set('WWW-Authenticate', challengeString)
|
|
}
|
|
|
|
//TODO: Allow response body to be JSON (maybe autodetect?)
|
|
const response = getResponseBody(req)
|
|
|
|
if(typeof response == 'string')
|
|
return res.status(401).send(response)
|
|
|
|
return res.status(401).json(response)
|
|
}
|
|
|
|
function authorizerCallback(err, approved) {
|
|
assert.ifError(err)
|
|
|
|
if(approved)
|
|
return next()
|
|
|
|
return unauthorized()
|
|
}
|
|
}
|
|
}
|
|
|
|
buildMiddleware.safeCompare = safeCompare
|
|
module.exports = buildMiddleware
|