This document provides instructions for generating MigratoryData JWT tokens with Node.js.

Signing algorithms

MigratoryData JWT Authorization add-on supports both symmetric and asymmetric signatures:

HMAC

This symmetric signature method uses a secret key for signing the JWT tokens by your backend. The same secret key must be used for verifying the JWT tokens by the JWT Authorization add-on. The signature algorithms supported by this method, automatically selected according to the length of the secret key, are as follows:

  • HS256 (HMAC SHA256), requires a 32-byte secret - recommended for most use cases
  • HS384 (HMAC SHA384), requires a 48-byte secret
  • HS512 (HMAC SHA512), requires a 64-byte secret

For example, to generate a 32-byte HMAC secret key, you can use the following command:

openssl rand -base64 32
Configure the parameter signature.hmac.secret of the JWT Authorization add-on with this HMAC secret key.

RSA

This asymmetric signature method uses a pair of public and private keys. The private key should be used by your backend for signing the JWT tokens. The public key should be used by the JWT Authorization add-on for verifying the JWT tokens. The signature algorithms supported by this method, automatically selected according to the length of the private key, are as follows:

  • RS256 (RSA SHA256), requires a 2048-bit private key - recommended for most use cases
  • RS384 (RSA SHA384), requires a 3072-bit private key
  • RS512 (RSA SHA512), requires a 4096-bit private key

For example, to generate a 2048-bit RSA pair of keys, you can use the following commands. Generate a private key using this command:

openssl genrsa \
-out rsa-private-key.pem \
2048

Then, extract the public key from the private key as follows:

openssl rsa -in rsa-private-key.pem \
-pubout \
-outform PEM \
-out rsa-public-key.pem
Copy the public key file rsa-public-key.pem to the JWT Authorization add-on folder and configure its parameter signature.rsa.publicKeyPath accordingly.

Node.js JWT tokens generator

You need to have installed Node.js and npm.

  1. Create a Node.js project and add the dependencies express (for http requests) and jsonwebtoken (for token generation) as follows:
npm init
npm install express
npm install jsonwebtoken@~8.5.1
  1. Create a javascript file index.js in the current project with the following content:
const express = require('express')
const jwt = require('jsonwebtoken')
const fs = require('fs')

const app = express()
const port = 8080

const subjectReg = new RegExp(/^\/([^\/]+\/)*([^\/]+|\*)$/);

const config = {
  username: 'admin',
  password: 'password',
  key: 'He39zDQW7RdkOcxe3L9qvoSQ/ef40BG6Ro4hrHDjE+U=', /* HMAC */
  //key: fs.readFileSync('rsa-private-key.pem'),       /* RSA */
}

function generateToken(permissions, ttl, key) {
  var token = jwt.sign({permissions: permissions}, Buffer.from(key, 'base64'), {expiresIn: ttl});   /* HMAC */
  //var token = jwt.sign({permissions: permissions}, key, { algorithm: 'RS256', expiresIn: ttl });  /* RSA */
  return token;
}

function isSubjectValid(subject) {
  return subjectReg.test(subject);
}

app.use(express.json());

app.post('/token/generate', (req, res) => {
  console.log(req.body);

  if (req.body.username !== config.username || req.body.password !== config.password) {
    res.status(400).json({response: 'Invalid username or password!'});
  }

  for (let permission in req.body.permissions) {
    for (let subject of req.body.permissions[permission]) {
      if (!isSubjectValid(subject)) {
        res.status(400).json({response: `Error, invalid subject format for subject: ${subject}`});
        return;
      }  
    }
}

  res.json({response: generateToken(req.body.permissions, req.body.ttlSeconds, config.key)});
})

app.listen(port, () => {
  console.log(`JWT token generator is listening on port ${port}`)
})
  1. Run the JWT token generator
node index.js
  1. Generate JWT tokens with publish and subscribe permissions for subjects

For example, run the following command to generate a JWT token valid one hour (i.e. 3600 seconds) with the following permissions:

  • the client is authorized to subscribe to the subject /sensor/temp
  • the client is authorized to publish to the subject /sensor/notification
  • the client is authorized to both subscribe to and publish on the subject /server/status
curl -X POST http://127.0.0.1:8080/token/generate \
-H 'Content-Type: application/json' \
-d '{"username":"admin","password":"password", "ttlSeconds": 3600, "permissions": { "sub": ["/sensor/temp"], "pub": ["/sensor/notification"], "all" :["/server/status"]}}'