Skip to content

molekilla/hapi-passport-saml

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

88 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

hapi-passport-saml

A Hapi plugin that wraps passport-saml for SAML SSO (as SP) with support for multiple strategies

Looking for donators or sponsors for this project, or hire me as freelance? Contact me at molekilla at gmail

Version 2.1.0 is compatible with Hapi 17. For previous version, stay with 1.x.x

Current release

2.1.0

Install

npm install hapi-passport-saml

Configuration

Uses samlidp.io as IdP, read passport-saml for how to use options

const Hapi = require('hapi');
const saml = require('hapi-passport-saml');
const routes = require('./routes/');

const server = Hapi.Server({
  port,
});

const samlOptions = {
  // passport saml settings
  saml: {
    callbackUrl: 'http://localhost/api/sso/v1/assert',
    logoutCallbackUrl: 'http://localhost/api/sso/v1/notifylogout',
    logoutUrl: 'https://my-idp.samlidp.io/saml2/idp/SingleLogoutService.php',
    host: 'localhost',
    protocol: 'http',
    entryPoint: 'https://my-idp.samlidp.io/saml2/idp/SSOService.php',
    // Service Provider Private Signing Key
    privateCert: fs.readFileSync(__dirname + '/privateSigning.pem', 'utf-8'),
    // Service Provider Private Encryption Key
    decryptionPvk: fs.readFileSync(__dirname + '/privateEncryption.pem', 'utf-8'),
    // IdP Public Signing Key
    cert: fs.readFileSync(__dirname + '/publicKey.crt', 'utf-8'),
    issuer: 'my-saml'
  },
  // hapi-passport-saml settings
  config: {
    // Service Provider Public Signing Key *Required if privateCert is provided
    signingCert: fs.readFileSync(__dirname + '/publicKey.crt', 'utf-8'),
    // Service Provider Public Encryption Key *Required if decryptionPvk is provided
    decryptionCert: fs.readFileSync(__dirname + '/publicKey.crt', 'utf-8'),
    // Plugin Routes
    routes: {
      // SAML Metadata
      metadata: {
        path: '/api/sso/v1/metadata.xml',
      },
      // SAML Assertion
      assert: {
        path: '/api/sso/v1/assert',
      },
    },
    assertHooks: {
      // Assertion Response Hook
      // Use this to add any specific props for your business
      // or appending to existing cookie
      // or make use of the RelayState
      onResponse: (profile, request, h) => {
        if(request.payload.RelayState)
          return h.redirect(request.payload.RelayState);
        else
          return h.response();
      },
    }
  }
};

// Internal cookie settings
const schemeOpts = {
  password: '14523695874159852035.0',
  isSecure: false,
  isHttpOnly: false,
  ttl: 3600,
};

(async function start() {
  try {
    await server.register([
      { plugin: saml, options: samlOptions },
    ]);

    await server.auth.strategy('single-sign-on', 'saml', schemeOpts);
    await server.auth.default('single-sign-on');
    await server.route(routes);
    await server.start();
    console.log(`Server listening on ${port}`);
  } catch (e) {
    server.stop();
    console.error('Server stopped due to an error', e);
  }
}());

Note: Internal cookie name is hapi-passport-saml-cookie, if you need to read the SAML credentials for integration with other strategies, use assertion hook.

Multiple strategies

Use hapi-passport-saml as the last strategy. Tested with try and required modes.

  • required: If successful, returns credentials, else HTTP 200 with JSON
  • try: If successful, returns credentials, else empty credentials and isAuthenticated set to false

More info: Integrating hapi cookie with hapi passport saml v1.1.0

Demo application

Demo

References, Ideas and Based from

License

MIT