hapi-saml2

raw JSON →
5.1.3 verified Sat Apr 25 auth: no javascript

hapi-saml2 is a Hapi.js plugin providing SAML-based Single Sign On via the node-saml library. Version 5.1.3 is current stable. It supports @hapi/hapi v18-v21, and requires @hapi/boom >=7.2.0 as a peer dependency. Key differentiators: built specifically for Hapi.js ecosystem (inline with Hapi's plugin architecture), replaces older passport-saml dependency with modern node-saml, and offers customizable route prefixes and handler hooks (preLogin, postResponseValidationErrorHandler). Release cadence: occasional updates to match node-saml releases.

error Error: SAML instance is not configured
cause getSAMLOptions returned undefined or threw inside the function.
fix
Ensure getSAMLOptions always returns an object with required node-saml properties (entryPoint, cert, etc.).
error AssertionError: login must be a function
cause Login option is missing or not a function in plugin options.
fix
Add login: async (request, identifier, user) => { return true; } to options.
error TypeError: Cannot destructure property 'nameID' of 'user' as it is undefined
cause user parameter in login callback is undefined if SAML response lacks expected profile attributes.
fix
Check that Identity Provider sends NameID; use identifier (string) instead of user properties if only NameID is needed.
breaking Version 5.x replaced passport-saml with @node-saml/node-saml. Callback signatures changed: login now receives (request, identifier, user) instead of the old passport-based signature.
fix Update login callback to accept (request, identifier, user) and return boolean or object.
breaking Removed samlOptions top-level config. Use getSAMLOptions function instead.
fix Move SAML configuration into getSAMLOptions function that returns node-saml options.
deprecated Options like 'issuer', 'callbackUrl' directly in options root were removed. Must be inside getSAMLOptions return.
fix Place all SAML-specific options inside the object returned by getSAMLOptions.
gotcha The plugin requires @hapi/hapi v18 or later. Hapi v17 is not supported (will throw on register).
fix Upgrade @hapi/hapi to v18+ (tested up to v21).
gotcha The plugin modifies server routes automatically. If apiPrefix collides with existing routes, registration fails silently with Boom.conflict.
fix Ensure apiPrefix (default '/saml') is not already used by other plugins or routes.
npm install hapi-saml2
yarn add hapi-saml2
pnpm add hapi-saml2

Registers the hapi-saml2 plugin with required callbacks and dynamic SAML options from environment variables.

const Hapi = require('@hapi/hapi');
const server = Hapi.server({ port: 3000, host: 'localhost' });

const init = async () => {
  await server.register({
    plugin: require('hapi-saml2'),
    options: {
      getSAMLOptions: (request) => ({
        entryPoint: process.env.SAML_ENTRY_POINT ?? 'https://idp.example.com/ssos',
        cert: process.env.SAML_CERT ?? '',
        issuer: 'http://localhost:3000',
        callbackUrl: 'http://localhost:3000/saml/callback'
      }),
      login: async (request, identifier, user) => {
        // After SAML response validation, identifier is the NameID
        console.log(`User ${identifier} logging in`);
        return true;
      },
      logout: async (request) => {
        // Implement logout logic, e.g., clear session
        console.log('User logged out');
      },
      redirectUrlAfterSuccess: '/dashboard',
      redirectUrlAfterFailure: '/login'
    }
  });
  await server.start();
  console.log('Server running on %s', server.info.uri);
};

init().catch(console.error);