Hapi.js JWT Authentication Plugin

11.0.0 · active · verified Wed Apr 22

Hapi-auth-jwt2 is a robust authentication scheme and plugin designed for Hapi.js applications, enabling secure user authentication through JSON Web Tokens (JWTs). The current stable version is 11.0.0. The project demonstrates an active release cadence, with recent version bumps addressing dependency updates, enhancing error handling, and implementing minor breaking changes to align with evolving ecosystem standards like ESLint. Its key differentiators include deep integration within the Hapi framework as a first-party plugin, a flexible `validate` function for custom user authentication logic, and support for advanced features such as 'try mode' and compatibility with multiple authentication strategies. The plugin prioritizes developer-friendliness, offering clear usage examples and comprehensive guidance on both Hapi.js and JWT fundamentals.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates setting up a Hapi server with `hapi-auth-jwt2`. It includes a mock user database, a custom `validate` function to verify decoded JWTs, and registers the plugin. The example configures a 'jwt' authentication strategy, sets it as the default, and defines two routes: a public one and a restricted one. A `/login` route is also provided to issue a sample JWT, making the example fully runnable for testing authentication flow.

const Hapi = require('@hapi/hapi');
const JWT = require('jsonwebtoken'); // Install 'jsonwebtoken' if you intend to sign tokens

const users = { // Our mock "users database"
  1: {
    id: 1,
    name: 'Jen Jones',
    scope: ['admin']
  }
};

// Define your token validation function
const validate = async function (decoded, request, h) {
  // In a real application, perform comprehensive checks (e.g., database lookup)
  if (!users[decoded.id]) {
    return { isValid: false };
  }
  // Return isValid: true and provide credentials for request.auth.credentials
  return { isValid: true, credentials: users[decoded.id] };
};

const init = async () => {
  const server = new Hapi.server({ port: 8000, host: 'localhost' });

  // Register the hapi-auth-jwt2 plugin
  await server.register(require('hapi-auth-jwt2'));

  // Configure the JWT authentication strategy
  server.auth.strategy('jwt', 'jwt',
    { key: process.env.JWT_SECRET ?? 'super-secret-jwt-key-replace-me',
      validate,
      verifyOptions: { algorithms: ['HS256'] } // Specify the algorithm if known
    });

  // Set 'jwt' as the default authentication strategy for all routes unless overridden
  server.auth.default('jwt');

  server.route([
    {
      method: "GET", path: "/", config: { auth: false }, // No authentication required
      handler: function(request, h) {
        return {text: 'Public route: Token not required. Try POST /login to get a token, then GET /restricted.'};
      }
    },
    {
      method: 'GET', path: '/restricted', config: { auth: 'jwt' }, // JWT authentication required
      handler: function(request, h) {
        const response = h.response({ text: `Hello, ${request.auth.credentials.name}! You used a valid Token!` });
        response.header("Authorization", request.headers.authorization);
        return response;
      }
    },
    {
      method: 'POST', path: '/login', config: { auth: false }, // Public route to obtain a token
      handler: function(request, h) {
        // In a real app, securely validate username/password from request.payload
        const user = users[1]; // Simulate successful login for user with ID 1
        const token = JWT.sign({ id: user.id, name: user.name }, process.env.JWT_SECRET ?? 'super-secret-jwt-key-replace-me', { expiresIn: '1h', algorithm: 'HS256' });
        return { token };
      }
    }
  ]);

  await server.start();
  console.log('Server running at:', server.info.uri);
  console.log('\nTo test:\n1. POST /login to get a JWT.\n2. Copy the token.\n3. GET /restricted with "Authorization: Bearer <token>" header.');
  return server;
};

init().catch(err => {
  console.error('Error starting server:', err);
  process.exit(1);
});

view raw JSON →