Implement Single Sign-On SAML strategy with Node.js & Passport.js

Prakhar Jain
TechBlog
Published in
6 min readJun 9, 2020

Single sign-on (SSO) is a property of identity and access management (IAM) that enables users to securely authenticate with multiple applications and websites by logging in only once with just one set of credentials (username and password).

Here in this article, we will Implement Single Sign-On in a Node.js App with SAML authentication strategy using Passport.js middleware if you want to read more on Single Sign-on and SAML you can read this article below.

First, we need an Identity Provider which can be an organization’s active directory or any free identity provider like OneLogin. For testing purposes I used OneLogin identity provider it allows us to create a developer account and we can play around it https://developers.onelogin.com/

We can configure our App please follow documentation for more information.

We will configure this information from the SAML-Test connector into our Passport.js middleware.

This includes certificate, endpoint ie. entry point will be the entry point for our app this will redirect our app on the authentication page.

We need to configure our app information into the identity provider to establish trust.

Application details are all Service Provider’s configuration like issuer and consumer callback URL

Consumer URL we will configure Service Provider’s Callback Url which will be called on authentication success.

Above information provided by the identity provider which will set up trust between an identity provider and service provider. Here service provider will be a backend app that will make trust between multiple identity providers like Azure IDP, OneLogin, Google OAuth, and so on.

{
entryPoint: 'https://ad.example.net/adfs/ls/',
issuer: 'DEV-BrightLab',
callbackUrl: 'https://your-app.example.net/login/callback',
cert: 'MIICizCCAfQCCQCY8tKaMc0BMjANBgkqh ... W=='
}

Here we have details which we will set up in our service provider to establish a trust between the service provider and identity provider.

entryPoint: is the URL provided by Identity Provider which will be used to redirect users on the login page if not authenticated.

issuer: is a string provided to the Identity Provider to uniquely identify Service Provider.

callbackUrl: This will be the URL of the Service Provider which will consume the SAML response once authentication is done on Identity Provider. Identity Provider will call this URL.

cert: This is the certificate provided by Identity Provider. This will be used to establish the trust between Identity Provider and Service Provider.

Now we are ready to implement our service provider using Passport.js

Passport is authentication middleware for Node.js. extremely flexible and modular, Passport can be unobtrusively dropped into any Express-based web application. A comprehensive set of strategies support authentication using a username and password, Facebook, Twitter, and more.

npm install passport

Install passport-saml, it is a SAML 2.0 authentication provider for Passport, the Node.js authentication library. The code was originally based on Michael Bosworth’s express-saml library.

npm install passport-saml

First We will Setup our passport handler middleware with our identity provider configuration. This is for a single identity provider strategy.

Now we can configure this Passport middleware into our app and initialize it.

  • We will set up two routes one is the GET route which will be the entry point of SSO into the application. when it will be called passport will authenticate and verify the trust in between service provider and the identity provider.
  • Another will be the consumer which will be called by the identity provider once it validated the credentials. Here Request body will be a SAML which is a base64 encoded body here I used the Saml2js module to parse the assertion in the SAML body which will provide the details of user who logged in.

Here is the router code for the Router

This is a user login controller which creates the session set in response cookies and redirect response to a UI Application page.

Let's put this all together and see how all this works…..

First, we call GET API localhost:9000/user/v1/users/login/sso

  • This GET API call checks if the active session is there or not, In my case, there was no active session it redirects me on an identity provider login page.
  • Once I entered my username and then password it authenticate request on identity provider and then it called the callback URL of service provider which we configured in the identity provider.
  • This POST callback URL localhost:9000/user/v1/users/login/sso/callback created a session for the application by validating request and redirects to the application dashboard page.

Well, We have successfully configured SAML based Single Sign-On

What if we have a SAAS based multitenant application which has different organizations and we need to configure Single Sign-On with these organization's Active Directory or their identity provider, In this case, we can use Passport’s MultiSAML strategy where we can configure SAML configuration on demand, we can identify organizations by subdomain or we can pass path params to these above URL. Let's configure MultiSamlStrategy

Here getSamlOptions function will be invoked on passport.authenticate() middleware called here we are fetching SAML configuration from DB on the basis of request orgId and setting this config for this middleware.

Here we configure Routes with path params and also configured their value into identity provider.

He is how I configured my BrightLab application with my Organization’s Active Directory ie. Azure.

we provided callback URL as /login/sso/callback/orgNamehere orgName becomes the value for the path parm id and we fetch SAML configuration from DB by {orgId: orgName} and on calling login API it will be redirected to the meck azure login page.

On submitting id and password identity provider authenticates the request and calls the callback URL and Land on the dashboard Page. similarly, we can pass different org if we have configured it and stored it into our database and we can determine this on the basis on the subdomain as well.

--

--