How to properly generate X-JWS-Signature in JS based on RFC 7515

521 Views Asked by At

I am trying to generate JWS signature for PSD2 purposes (RFC 7515). I have the following functions:

function signJson(json, privateKey) {
  const header = {
    alg: 'RS256',
    typ: 'JWT'
  };
  const payload = JSON.stringify(json);
  const data = base64UrlEncode(header) + '.' + base64UrlEncode(payload);
  const signature = crypto.createSign('RSA-SHA256').update(data).sign(privateKey, 'base64');
  return data + '.' + signature;
}

function base64UrlEncode(data) {
  return data.toString('base64')
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=+$/, '');
}

But the returning string is wrong JWT as it not begins with "ey". Where I am making mistake?

1

There are 1 best solutions below

0
On

Here is how we did this using the node-jwa library, probably the same can be done with crypto.createSign.

const fs = require("fs");
const jwa = require("jwa");

const getJWTHeader = () => {
  return encodeData({
    typ: "JWT",
    alg: "RS256"
  })
}

const encodeData = (data) => {
  return Buffer.from(JSON.stringify(data)).toString("base64").replace("=", "")
}

const getJWTBody = (exp) => {
  const timestamp = Math.floor((new Date()).getTime() / 1000)
  return encodeData({
    iss: "YOUR ISSUER HERE",
    aud: "YOUR AUDIENCE HERE",
    iat: timestamp,
    exp: timestamp + exp,
    // maybe some other fields are necessary
  })
}

const signWithKey = (data) => {
  const key = fs.readFileSync("PATH TO THE PRIVATE KEY IN PEM", "utf8");
  const hmac = jwa("RS256");
  return hmac.sign(data, key);
}

const getJWT = (exp = 3600) => {
  const jwtHeaders = getJWTHeader()
  const jwtBody = getJWTBody(exp);
  const jwtSignature = signWithKey(`${jwtHeaders}.${jwtBody}`)
  return `${jwtHeaders}.${jwtBody}.${jwtSignature}`
}

console.log(getJWT())