Menu Close

Server-Side Development with Hapi.js — Tokens, JWT, and Secrets

Hapi.js is a small Node framework for developing back end web apps.

In this article, we’ll look at how to create back end apps with Hapi.js.

Create Tokens

We can create tokens with the @hapi/iron module.

For example, we can write:

const Hapi = require('@hapi/hapi');
const iron = require('@hapi/iron')

const obj = {
  a: 1,
  b: 2,
  c: [3, 4, 5],
  d: {
      e: 'f'
  }
};

const password = 'passwordpasswordpasswordpassword';

const init = async () => {
  const server = new Hapi.Server({
    port: 3000,
    host: '0.0.0.0'
  });

  server.route({
    method: 'GET',
    path: '/',
    async handler(request, h) {
      try {
        const sealed = await iron.seal(obj, password, iron.defaults);
        return sealed
      } catch (err) {
        console.log(err);
      }
    }
  });

  await server.start();
  console.log('Server running at:', server.info.uri);
};

process.on('unhandledRejection', (err) => {
  console.log(err);
  process.exit(1);
});
init();

We call the iron.seal method with the object we want to encrypt, the password to access the encrypted object, and the settings, which is iron.defaults .

Them the sealed string is a scrambled version of the object in string form.

Then to unseal it, we call the iron.unseal method.

For example, we can write:

const Hapi = require('@hapi/hapi');
const iron = require('@hapi/iron')

const obj = {
  a: 1,
  b: 2,
  c: [3, 4, 5],
  d: {
      e: 'f'
  }
};

const password = 'passwordpasswordpasswordpassword';

const init = async () => {
  const server = new Hapi.Server({
    port: 3000,
    host: '0.0.0.0'
  });

  server.route({
    method: 'GET',
    path: '/',
    async handler(request, h) {
      try {
        const sealed = await iron.seal(obj, password, iron.defaults);
        const unsealed = await iron.unseal(sealed, password, iron.defaults);
        return unsealed
      } catch (err) {
        console.log(err);
      }
    }
  });

  await server.start();
  console.log('Server running at:', server.info.uri);
};

process.on('unhandledRejection', (err) => {
  console.log(err);
  process.exit(1);
});
init();

to decrypt the encrypted string with the same password with the iron.unseal method.

JSON Web Token

We can create and verify JSON web tokens with the @hapi/jwt module.

For example, we can use it by writing:”

const Hapi = require('@hapi/hapi');
const Jwt = require('@hapi/jwt');
const jwt = require('jsonwebtoken');

const init = async () => {
  const server = new Hapi.Server({
    port: 3000,
    host: '0.0.0.0'
  });

  await server.register(Jwt);

  server.auth.strategy('my_jwt_stategy', 'jwt', {
    keys: 'some_shared_secret',
    verify: {
      aud: 'urn:audience:test',
      iss: 'urn:issuer:test',
      sub: false,
      nbf: true,
      exp: true,
      maxAgeSec: 14400,
      timeSkewSec: 15
    },
    validate: (artifacts, request, h) => {
      return {
        isValid: true,
        credentials: { user: artifacts.decoded.payload.user }
      };
    }
  });

  server.route({
    method: 'GET',
    path: '/',
    config: {
      handler(request, h) {
        const token = jwt.sign({
          aud: 'urn:audience:test',
          iss: 'urn:issuer:test',
          sub: false,
          maxAgeSec: 14400,
          timeSkewSec: 15
        }, 'some_shared_secret');
        return token;
      },

}
  });

  server.route({
    method: 'GET',
    path: '/secret',
    config: {
      handler(request, h) {
        return 'secret';
      },
      auth: {
        strategy: 'my_jwt_stategy',
      }
    }
  });

  await server.start();
  console.log('Server running at:', server.info.uri);
};

process.on('unhandledRejection', (err) => {
  console.log(err);
  process.exit(1);
});
init();

We add the jsonwebtoken module to create the token.

Then we call server.auth.strategy to add the JWT auth strategy.

The keys have the keys we use to verify the token.

verify has the fields we want to verify.

validate has a function that returns isValid to indicate that the token is valid.

credentials have the data from the decoded token.

Then we call jwt.sign to sign the token in the / route handler.

And in the /secret route, we have the auth.strategy property to set the auth strategy.

Conclusion

We can create various kinds of tokens and verify them with Hapi addons.

Posted in Hapi