Skip to content

Instantly share code, notes, and snippets.

@robingustafsson
Created October 14, 2017 20:16
Show Gist options
  • Save robingustafsson/7dd6463d85efdddbb0e4bcd3ecc706e1 to your computer and use it in GitHub Desktop.
Save robingustafsson/7dd6463d85efdddbb0e4bcd3ecc706e1 to your computer and use it in GitHub Desktop.
Simple JWT example for k6 load testing tool
import crypto from "k6/crypto";
import encoding from "k6/encoding";
const algToHash = {
HS256: "sha256",
HS384: "sha384",
HS512: "sha512"
};
function sign(data, hashAlg, secret) {
let hasher = crypto.createHMAC(hashAlg, secret);
hasher.update(data);
// Some manual base64 rawurl encoding as `Hasher.digest(encodingType)`
// doesn't support that encoding type yet.
return hasher.digest("base64").replace(/\//g, "_").replace(/\+/g, "-").replace(/=/g, "");
}
function encode(payload, secret, algorithm) {
algorithm = algorithm || "HS256";
let header = encoding.b64encode(JSON.stringify({ typ: "JWT", alg: algorithm }), "rawurl");
payload = encoding.b64encode(JSON.stringify(payload), "rawurl");
let sig = sign(header + "." + payload, algToHash[algorithm], secret);
return [header, payload, sig].join(".");
}
function decode(token, secret, algorithm) {
let parts = token.split('.');
let header = JSON.parse(encoding.b64decode(parts[0], "rawurl"));
let payload = JSON.parse(encoding.b64decode(parts[1], "rawurl"));
algorithm = algorithm || algToHash[header.alg];
if (sign(parts[0] + "." + parts[1], algorithm, secret) != parts[2]) {
throw Error("JWT signature verification failed");
}
return payload;
}
export default function() {
let message = { key2: "value2" };
let token = encode(message, "secret");
console.log("encoded", token);
let payload = decode(token, "secret");
console.log("decoded", JSON.stringify(payload));
}
@mbforbes
Copy link

mbforbes commented Feb 9, 2024

In case anyone's still looking how to do this 7 (!) years later, there seem to have been a few updates to the k6 JS libraries:

  • hasher.digest now supports "base64rawurl"
  • encoding.b64decode now requires a third parameter "s" to return the result as a string and not an ArrayBuffer

Here is the script with those updates, basic type annotations, encode() / decode(), and the test function removed:

import crypto from "k6/crypto";
import encoding from "k6/encoding";

const algToHash = {
  HS256: "sha256",
  HS384: "sha384",
  HS512: "sha512",
};

function sign(data, hashAlg, secret) {
  const hasher = crypto.createHMAC(hashAlg, secret);
  hasher.update(data);
  return hasher.digest("base64rawurl");
}

/**
 *
 * @param {Object} payload
 * @param {string} secret
 * @param {string|undefined} algorithm Default: "HS256"
 * @returns string
 */
export function encode(payload, secret, algorithm) {
  algorithm = algorithm || "HS256";
  const header = encoding.b64encode(
    JSON.stringify({ typ: "JWT", alg: algorithm }),
    "rawurl"
  );
  payload = encoding.b64encode(JSON.stringify(payload), "rawurl");
  const sig = sign(header + "." + payload, algToHash[algorithm], secret);
  return [header, payload, sig].join(".");
}

/**
 *
 * @param {string} token
 * @param {string} secret
 * @param {string|undefined} algorithm
 * @returns
 */
export function decode(token, secret, algorithm) {
  const parts = token.split(".");
  const header = JSON.parse(encoding.b64decode(parts[0], "rawurl", "s"));
  const payload = JSON.parse(encoding.b64decode(parts[1], "rawurl", "s"));
  algorithm = algorithm || algToHash[header.alg];
  if (sign(parts[0] + "." + parts[1], algorithm, secret) != parts[2]) {
    throw Error("JWT signature verification failed");
  }
  return payload;
}

I'm importing the functions like this from my k6 script:

import { encode, decode } from "./jwt.js";

// example code from the original gist:
let message = { key2: "value2" };
let token = encode(message, "secret");
console.log("encoded", token);
let payload = decode(token, "secret");
console.log("decoded", JSON.stringify(payload));

Also of note: k6's documentation points out they have an experimental webcrypto package they recommend using. So future iterations on this might want to check it out.

@DJDANNY123
Copy link

DJDANNY123 commented Jun 14, 2024

Thanks for this example, I used it to help me with the encoding for signing a JWT using the new experimental webcrypto package, which I'll link below so others can find:

https://gist.github.com/DJDANNY123/7e597deab553ada6b68110e3ebcfa322#file-signing-utils-ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment