UNPKG

gitlab-acebase

Version:

AceBase realtime database server (webserver endpoint to allow remote connections)

73 lines 2.8 kB
import * as crypto from 'crypto'; export const createPublicAccessToken = (uid, ip, dbToken, password) => { const obj = { t: dbToken, c: Date.now(), u: uid, i: ip, }; // let str = JSON.stringify(obj); // str = Buffer.from(str).toString('base64'); // return 'a' + str; // version a return 'b' + createSignedPublicToken(obj, password); }; export const decodePublicAccessToken = (accessToken, password) => { let details; if (accessToken[0] === 'b') { // New signed version const obj = parseSignedPublicToken(accessToken.slice(1), password); details = { access_token: obj.t, uid: obj.u, created: obj.c, ip: obj.i, }; } else if (accessToken[0] === 'a') { // Old insecure version, previously allowed until August 1, 2020. throw new Error('Old token version not allowed'); } if (!details || !details.access_token || !details.uid || !details.created || !details.ip) { throw new Error('Invalid token'); } return details; }; const getSignature = (content, salt) => { // Use fast md5 with salt to sign with. Large salt recommended!! return crypto.createHash('md5').update(salt + content).digest('hex'); }; /** * Sign objects with an md5 hash. An attacker might base4 decode it and see the content and generated checksum hash, * but will need to guess the password used to generate the hash to manipulate it. This is not impossible but will take * a very long time when using a large password * @param obj data object to sign * @param password password to use as salt for the generated md5 hash * @returns base64 encoded signed token */ export const createSignedPublicToken = (obj, password) => { const str = JSON.stringify(obj); const checksum = getSignature(str, password); return Buffer.from(JSON.stringify({ v: 1, cs: checksum, d: str })).toString('base64'); }; /** * Parses and validates a signed token that was previouslt generated by `createSignedPublicToken` * @param str token previously generated by `createSignedPublicToken` * @param password the same password used to create the token with * @returns the original data object */ export const parseSignedPublicToken = (str, password) => { const json = Buffer.from(str, 'base64').toString('utf8'); const obj = JSON.parse(json); if (obj.v !== 1) { throw new Error(`Unsupported version`); } if (typeof obj.cs !== 'string' || typeof obj.d !== 'string') { throw new Error('Invalid token'); } const checksum = obj.cs; if (checksum !== getSignature(obj.d, password)) { throw new Error(`compromised object`); } return JSON.parse(obj.d); }; //# sourceMappingURL=tokens.js.map