Skip to content

Instantly share code, notes, and snippets.

@kimsible
Last active July 3, 2019 22:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kimsible/cf57e18764b154c9e45ce33daa45b595 to your computer and use it in GitHub Desktop.
Save kimsible/cf57e18764b154c9e45ce33daa45b595 to your computer and use it in GitHub Desktop.
'use strict'
const crypto = require('crypto')
const path = require('path')
const mudb = require('mudb')
const { STORAGE, SALT } = process.env
let db
async function load () {
const authList = path.resolve(STORAGE || process.cwd(), './auth.json')
db = await mudb.open(authList)
}
const encrypt = (string, salt = SALT) => {
if (salt) {
return new Promise((resolve, reject) => {
crypto.pbkdf2(string, salt, 100000, 32, 'sha512', (error, data) => {
if (error) {
return reject(error)
}
return resolve(data.toString('base64'))
})
})
} else {
return string
}
}
const credentials = req => {
const { authorization } = req.headers
try {
const [, base64Credentials] = (authorization || '').match(/^Basic (.+)$/)
return Buffer.from(base64Credentials, 'base64').toString('ascii').split(':')
} catch {
return []
}
}
const access = async req => {
const [email, id] = credentials(req)
if (db.get({ email: await encrypt(email), id: await encrypt(id) }).length === 0) {
throw new Error('Unauthorized Error')
}
}
const get = async id => {
if (db.get({ id: await encrypt(id) }).length === 0) {
throw new Error('Unauthorized Error')
}
}
const create = async email => {
const id = crypto.randomBytes(3 * 8).toString('base64')
const encryptedEmail = await encrypt(email)
if (db.get({ email: encryptedEmail }).length > 0) {
db.del({ email: encryptedEmail })
}
db.add({ email: encryptedEmail, id: await encrypt(id) }).save()
return id
}
const remove = async email => {
db.del({ email: await encrypt(email) }).save()
}
module.exports = {
load,
encrypt,
credentials,
access,
get,
create,
remove
}
'use strict'
import test from 'ava'
import auth from './auth'
test('auth/encrypt - no salt / no encryption', authEncryptTest, 'email@provider.com')
test('auth/encrypt - with salt', authEncryptTest, 'email@provider.com', 'salt')
async function authEncryptTest (t, input, salt) {
const encrypted = await auth.encrypt(input, salt)
if (salt) {
t.not(encrypted, input)
} else {
t.is(encrypted, input)
}
}
test('auth/credentials - OK', authCredentialsTest, `Basic ${Buffer.from('user@provider.com:GwJexPcIEeAnPTtH091ynxodjXCo86/j').toString('base64')}`, { email: 'user@provider.com', id: 'GwJexPcIEeAnPTtH091ynxodjXCo86/j' })
test('auth/credentials - wrong header', authCredentialsTest, `${Buffer.from('user@provider.com:GwJexPcIEeAnPTtH091ynxodjXCo86/j').toString('base64')}`, { email: undefined, id: undefined })
function authCredentialsTest (t, input, output) {
const [email, id] = auth.credentials({
headers: {
authorization: input
}
})
t.is(email, output.email)
t.is(id, output.id)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment