Skip to content

Instantly share code, notes, and snippets.

@ronnievsmith
Last active August 23, 2023 02:33
Show Gist options
  • Save ronnievsmith/2d5ee18f32695479b34eac75d67aae88 to your computer and use it in GitHub Desktop.
Save ronnievsmith/2d5ee18f32695479b34eac75d67aae88 to your computer and use it in GitHub Desktop.

Revisions

  1. Ronnie Royston revised this gist Aug 23, 2023. No changes.
  2. Ronnie Royston created this gist Aug 22, 2023.
    97 changes: 97 additions & 0 deletions jws-hs256.mjs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,97 @@
    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;
    }