Skip to content

Instantly share code, notes, and snippets.

@ronnieroyston
Last active August 23, 2023 02:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ronnieroyston/2d5ee18f32695479b34eac75d67aae88 to your computer and use it in GitHub Desktop.
Save ronnieroyston/2d5ee18f32695479b34eac75d67aae88 to your computer and use it in GitHub Desktop.
JSON Web Signature (JWS) Token via HMAC using SHA-256 w Node.js Crypto Module
import { Buffer } from 'node:buffer';
import fs from "node:fs";
import url from 'node:url';
import path from "node:path";
const {createHmac, generateKey} = await import('node:crypto');
var claims = {name:"Joe",roles:["member","admin"]};
var secretKey;
(async function () {
secretKey = await generateSecretKey();
let jws = await returnJWS(claims);
console.log("\x1b[37mYour JWS token is: " + consoleString(jws));
console.log("Paste JSON Web Token In Terminal Then Press Enter.")
})();
function returnJWS(claims){
let headerObject = {
alg: 'HS256',
typ: 'JWT',
kid: 'public'
};
let headerString = JSON.stringify(headerObject);
let encodedHeader = Buffer.from(headerString).toString('base64url');
let payloadString = JSON.stringify(claims);
let encodedPayload = Buffer.from(payloadString).toString('base64url');
const hmac = createHmac('sha256', secretKey);
hmac.update(encodedHeader + '.' + encodedPayload);
let signature = hmac.digest('base64url');
let jsonWebToken = encodedHeader + '.' + encodedPayload + '.' + signature;
return jsonWebToken;
}
function validateJWS(jwt){
try {
let jwtParts = jwt.split('.');
let jwtHeader = jwtParts[0];
let jwtPayload = jwtParts[1];
let jwtSignature = jwtParts[2].trim();
let signature;
let header = JSON.parse(Buffer.from(jwtHeader, 'base64url').toString('utf-8'));
let alg = header.alg;
if(alg === "HS256"){
const hmac = createHmac('sha256', secretKey);
hmac.update(jwtHeader + '.' + jwtPayload);
signature = hmac.digest('base64url').trim();
console.log(signature)
console.log(jwtSignature)
if(signature == jwtSignature) {
return Buffer.from(jwtPayload, 'base64url').toString('utf-8')
} else {
return "\x1b[31mInvalid Token!\x1b[37m";
}
} else {
throw (error)
}
} catch (e) {
console.log (e);
return "\x1b[31mInvalid Token!\x1b[37m";
}
}
function generateSecretKey () {
return new Promise(function(resolve, reject) {
generateKey('aes', { length: 256 }, (err, key) => {
if (err) {
reject (err);
}
resolve (key)
});
});
}
export default {returnJWS, validateJWS};
process.stdin.setEncoding('utf8');
process.stdin.on('readable', async () => {
let chunk;
while ((chunk = process.stdin.read()) !== null) {
console.log(await validateJWS(chunk));
}
});
function consoleString(token){
let tokenParts = token.split(/(\.)/);
let colors = ["32m","31m","33m","34m","36m"];
let color = "\x1b[X";
let str = ""
tokenParts.forEach(function(part,index){
if(part != "."){
str += color.replace("X",colors.shift())
}
str += part;
str += "\x1b[37m"
})
return str;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment