const crypto = require("crypto"); const jwt = require("jsonwebtoken"); const db = require("./utils/data"); const secretKey = require("./secretKey"); function getCurrentSeconds() { return Math.floor(Date.now() / 1000); } function createTokenId() { return crypto.randomBytes(16).toString("hex"); } function createToken(scopes = {}) { return new Promise((resolve, reject) => { const payload = { jti: createTokenId(), iss: "https://unpkg.com", iat: getCurrentSeconds(), scopes }; jwt.sign( payload, secretKey.private, { algorithm: "RS256" }, (error, token) => { if (error) { reject(error); } else { resolve(token); } } ); }); } const revokedTokensSet = "revoked-tokens"; function verifyToken(token) { return new Promise((resolve, reject) => { const options = { algorithms: ["RS256"] }; jwt.verify(token, secretKey.public, options, (error, payload) => { if (error) { reject(error); } else { if (payload.jti) { db.sismember(revokedTokensSet, payload.jti, (error, value) => { if (error) { reject(error); } else { resolve(value === 0 ? payload : null); } }); } else { resolve(null); } } }); }); } function revokeToken(token) { return verifyToken(token).then(payload => { if (payload) { return new Promise((resolve, reject) => { db.sadd(revokedTokensSet, payload.jti, error => { if (error) { reject(error); } else { resolve(); } }); }); } }); } function removeAllRevokedTokens() { return new Promise((resolve, reject) => { db.del(revokedTokensSet, error => { if (error) { reject(error); } else { resolve(); } }); }); } function getPublicKey() { return secretKey.public; } module.exports = { createToken, verifyToken, revokeToken, removeAllRevokedTokens, getPublicKey };