UNPKG

@bee.js/node

Version:

A JavaScript framework for making Node.js API´s

108 lines (82 loc) 3.19 kB
const CryptoJS = require("crypto-js"); const log = require("../beeHive/log"); const bee = { tools: require("../../tools/beeTools") }; function base64url(source) { let encodedSource = CryptoJS.enc.Base64.stringify(source); encodedSource = encodedSource.replace(/=+$/, ""); encodedSource = encodedSource.replace(/\+/g, "-"); encodedSource = encodedSource.replace(/\//g, "_"); return encodedSource; } function base64urlDecode(input = "") { if (!input) return ""; let normalized = input.replace(/-/g, "+").replace(/_/g, "/"); const pad = normalized.length % 4; if (pad) normalized += "=".repeat(4 - pad); return Buffer.from(normalized, "base64").toString("utf8"); } module.exports = function token(_payload = null, header = {}, options = {}) { if (_payload) { let { jwt, ...payload } = _payload; if (!global.configs.jwt && !global.configs.jwt.secret) return log("ERROR: no jwt.secret defined in configs."); let secret = global.configs.jwt.secret; let iat = new Date().getTime(); // options.expires is in minutes (default: 1 minute) const expiresInMinutes = typeof options.expires === "number" ? options.expires : 1; let exp = new Date().getTime() + expiresInMinutes * 60 * 1000; header = { ...header, typ: header.typ || "JWT", alg: header.alg || "HS256", }; payload = { ...payload, iat: iat, exp: exp }; header = base64url(CryptoJS.enc.Utf8.parse(JSON.stringify(header))); payload = base64url(CryptoJS.enc.Utf8.parse(JSON.stringify(payload))); const signature = base64url( CryptoJS.HmacSHA256(`${header}.${payload}`, secret) ); const token = `${header}.${payload}.${signature}`; this.data.jwt = this.data.jwt && typeof this.data.jwt !== "object" ? [this.data.jwt] : this.data.jwt; this.data.jwt = !this.data.jwt ? token : this.data.jwt.concat(token); this.counters.jwt = (this.counters.jwt || 0) + 1; log("JWT created: " + this.data.jwt); return this; } return { ...this, verify: function (token, headers = {}) { const secret = global.configs.jwt.secret; const apiKey = headers["x-api-key"] || headers["api-key"] || headers["apikey"]; // Acesso de maquinas via API key (md5 do segredo JWT). if (apiKey && apiKey === bee.tools.md5(secret)) { return JSON.stringify({ machine: true }); } if (!token || typeof token !== "string") return false; const array = token.split("."); if (array.length !== 3) return false; const header = array[0]; const payload = array[1]; const signature = base64url( CryptoJS.HmacSHA256(`${header}.${payload}`, secret) ); if (token !== `${header}.${payload}.${signature}`) return false; let payloadDecoded = base64urlDecode(payload); let payloadJson; try { payloadJson = JSON.parse(payloadDecoded); } catch (error) { return false; } if (payloadJson?.exp && new Date().getTime() > payloadJson.exp) { return { error: { message: "TOKEN_EXPIRED", status: 419 } }; } return payloadDecoded; }, }; };