1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
| const crypto = require('crypto'); const sha = require('sha.js');
const sha256 = (...messages) => { const hash = sha('sha256'); messages.forEach((m) => hash.update(m)); return hash.digest('hex'); };
const JWT_SECRET = crypto.randomBytes(9).toString('hex');
const toBase64Url = (input) => { const buffer = Buffer.isBuffer(input) ? input : Buffer.from(input); return buffer .toString('base64') .replace(/\+/g, '-') .replace(/\//g, '_') .replace(/=+$/, ''); };
const fromBase64Url = (input) => { const paddedLength = (4 - (input.length % 4)) % 4; const base64 = input.replace(/-/g, '+').replace(/_/g, '/') + '='.repeat(paddedLength); return Buffer.from(base64, 'base64'); };
const hashPassword = (password, salt = '') => sha256(password, salt);
const signJWT = (payload, { expiresIn } = {}, secret = JWT_SECRET) => { const header = { alg: 'HS256', typ: 'JWT' }; const now = Math.floor(Date.now() / 1000); console.log(payload) const body = { ...payload, length:payload.username.length,iat: now }; if (expiresIn) { body.exp = now + expiresIn; }
return [ toBase64Url(JSON.stringify(header)), toBase64Url(JSON.stringify(body)), sha256(...[JSON.stringify(header), body, secret]) ].join('.'); };
const verifyJWT = (token, secret = JWT_SECRET) => { if (typeof token !== 'string') { return null; }
const parts = token.split('.'); if (parts.length !== 3) { return null; }
const [encodedHeader, encodedPayload, signature] = parts;
let header; let payload; try { header = JSON.parse(fromBase64Url(encodedHeader).toString()); payload = JSON.parse(fromBase64Url(encodedPayload).toString()); } catch (err) { return null; }
const expectedSignatureHex = sha256(...[JSON.stringify(header), payload, secret]);
let providedSignature; let expectedSignature; try { providedSignature = Buffer.from(signature, 'hex'); expectedSignature = Buffer.from(expectedSignatureHex, 'hex'); } catch (err) { return null; }
if ( providedSignature.length !== expectedSignature.length || !crypto.timingSafeEqual(providedSignature, expectedSignature) ) { return null; }
if (header.alg !== 'HS256') { return null; }
if (payload.exp && Math.floor(Date.now() / 1000) >= payload.exp) { return null; }
return payload; };
module.exports = { hashPassword, signJWT, verifyJWT, };
|