Files
2026-05-05 10:24:46 +02:00

41 lines
1.6 KiB
JavaScript

// Snippet: JWT and password helpers for n8n Code nodes
// Usage: paste the needed functions into a Code node at the start of your webhook workflows.
const crypto = require('crypto');
function base64url(bufOrStr){
const b = Buffer.isBuffer(bufOrStr) ? bufOrStr : Buffer.from(String(bufOrStr));
return b.toString('base64').replace(/\+/g,'-').replace(/\//g,'_').replace(/=+$/,'');
}
function signJWT(payload, secret, expiresInSec=86400){
const header = base64url(JSON.stringify({ alg:'HS256', typ:'JWT' }));
const exp = Math.floor(Date.now()/1000) + expiresInSec;
const body = base64url(JSON.stringify({ ...payload, exp }));
const sig = base64url(crypto.createHmac('sha256', secret).update(`${header}.${body}`).digest());
return `${header}.${body}.${sig}`;
}
function verifyJWT(token, secret){
try {
const [h,b,s] = token.split('.');
const expected = base64url(crypto.createHmac('sha256', secret).update(`${h}.${b}`).digest());
if (expected !== s) return null;
const payload = JSON.parse(Buffer.from(b.replace(/-/g,'+').replace(/_/g,'/'),'base64').toString());
if (payload.exp && Math.floor(Date.now()/1000) > payload.exp) return null;
return payload;
} catch(e){ return null; }
}
function hashPassword(password){
const salt = crypto.randomBytes(16).toString('hex');
const derived = crypto.scryptSync(password, salt, 64).toString('hex');
return { salt, hash: derived };
}
function verifyPassword(password, salt, hash){
return crypto.scryptSync(password, salt, 64).toString('hex') === hash;
}
module.exports = { signJWT, verifyJWT, hashPassword, verifyPassword };