2020-07-23 00:46:05 +02:00
|
|
|
import crypto from 'crypto';
|
2020-08-08 02:19:42 +02:00
|
|
|
import { v4, v5, validate } from 'uuid';
|
2021-04-28 11:45:38 +02:00
|
|
|
import bcrypt from 'bcryptjs';
|
2020-07-23 06:33:17 +02:00
|
|
|
import { JWT, JWE, JWK } from 'jose';
|
2020-08-21 04:38:20 +02:00
|
|
|
import { startOfMonth } from 'date-fns';
|
2020-07-23 00:46:05 +02:00
|
|
|
|
2020-08-09 08:48:43 +02:00
|
|
|
const SALT_ROUNDS = 10;
|
2020-07-23 06:33:17 +02:00
|
|
|
const KEY = JWK.asKey(Buffer.from(secret()));
|
2020-08-21 04:38:20 +02:00
|
|
|
const ROTATING_SALT = hash(startOfMonth(new Date()).toUTCString());
|
2020-08-15 10:17:15 +02:00
|
|
|
const CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
2020-07-23 00:46:05 +02:00
|
|
|
|
2020-07-24 04:56:55 +02:00
|
|
|
export function hash(...args) {
|
|
|
|
return crypto.createHash('sha512').update(args.join('')).digest('hex');
|
2020-07-23 05:45:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export function secret() {
|
2020-07-24 04:56:55 +02:00
|
|
|
return hash(process.env.HASH_SALT);
|
2020-07-23 05:45:09 +02:00
|
|
|
}
|
2020-07-23 00:46:05 +02:00
|
|
|
|
2020-08-21 04:38:20 +02:00
|
|
|
export function salt() {
|
|
|
|
return v5([secret(), ROTATING_SALT].join(''), v5.DNS);
|
|
|
|
}
|
|
|
|
|
2020-07-23 05:45:09 +02:00
|
|
|
export function uuid(...args) {
|
2020-08-08 02:19:42 +02:00
|
|
|
if (!args.length) return v4();
|
|
|
|
|
2020-08-21 04:38:20 +02:00
|
|
|
return v5(args.join(''), salt());
|
2020-07-23 00:46:05 +02:00
|
|
|
}
|
|
|
|
|
2020-09-18 07:52:20 +02:00
|
|
|
export function isValidUuid(s) {
|
2020-08-08 02:19:42 +02:00
|
|
|
return validate(s);
|
2020-07-23 00:46:05 +02:00
|
|
|
}
|
|
|
|
|
2020-08-15 10:17:15 +02:00
|
|
|
export function getRandomChars(n) {
|
|
|
|
let s = '';
|
|
|
|
for (let i = 0; i < n; i++) {
|
|
|
|
s += CHARS[Math.floor(Math.random() * CHARS.length)];
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2020-08-09 11:03:37 +02:00
|
|
|
export async function hashPassword(password) {
|
2021-04-28 11:45:38 +02:00
|
|
|
return bcrypt.hashSync(password, SALT_ROUNDS);
|
2020-08-09 08:48:43 +02:00
|
|
|
}
|
|
|
|
|
2020-08-09 11:03:37 +02:00
|
|
|
export async function checkPassword(password, hash) {
|
2021-04-28 11:45:38 +02:00
|
|
|
return bcrypt.compareSync(password, hash);
|
2020-07-23 00:46:05 +02:00
|
|
|
}
|
|
|
|
|
2020-07-23 06:33:17 +02:00
|
|
|
export async function createToken(payload) {
|
|
|
|
return JWT.sign(payload, KEY);
|
2020-07-23 00:46:05 +02:00
|
|
|
}
|
|
|
|
|
2020-08-08 02:19:42 +02:00
|
|
|
export async function parseToken(token) {
|
|
|
|
try {
|
|
|
|
return JWT.verify(token, KEY);
|
|
|
|
} catch {
|
|
|
|
return null;
|
|
|
|
}
|
2020-07-23 06:33:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export async function createSecureToken(payload) {
|
|
|
|
return JWE.encrypt(await createToken(payload), KEY);
|
|
|
|
}
|
|
|
|
|
2020-08-08 02:19:42 +02:00
|
|
|
export async function parseSecureToken(token) {
|
|
|
|
try {
|
|
|
|
const result = await JWE.decrypt(token, KEY);
|
|
|
|
|
|
|
|
return parseToken(result.toString());
|
|
|
|
} catch {
|
|
|
|
return null;
|
|
|
|
}
|
2020-07-23 00:46:05 +02:00
|
|
|
}
|