npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@liveramp/oidc-middleware

v0.2.0

Published

Forked version of OIDC Middleware OpenId Connect middleware for authorization code flows

Downloads

2

Readme

oidc-middleware

npm version build status

This package makes it easy to get your users logged in with Okta using OpenId Connect (OIDC). It enables your Express application to participate in the authorization code flow flow by redirecting the user to Okta for authentication and handling the callback from Okta. Once this flow is complete, a local session is created and the user context is saved for the duration of the session.

:warning: :construction: Alpha Preview :construction: :warning:

This library is under development and is currently in 0.x version series. Breaking changes may be introduced at minor versions in the 0.x range. Please lock your dependency to a specific version until this library reaches 1.x.

Need help? Contact [email protected] or use the Okta Developer Forum.

Table of Contents

Installation

npm install --save @okta/oidc-middleware

Prerequisites

  • You will need an Okta Developer Org, you can sign up for an account at https://developer.okta.com/signup/..
  • An OIDC application in your Org, configured for Web mode. If you are new to Okta or this flow, we suggest following the Express.js Quickstart.
  • This integration depends on sessions to store user information. Ensure the express-session middleware is added before you add ExpressOIDC. By default, the session middleware uses a MemoryStore, which is not designed for production use. Use another session store for production.

Usage Example

Below is a terse Express application that examples the basic usage of this library. If you'd like to clone a complete example, please see the Okta Express Samples Repository.

const express = require('express');
const session = require('express-session');
const { ExpressOIDC } = require('@okta/oidc-middleware');

const app = express();
const oidc = new ExpressOIDC({
  issuer: 'https://{yourOktaDomain}.com/oauth2/default',
  client_id: 'XXXXX',
  client_secret: 'XXXXX',
  redirect_uri: 'http://localhost:3000/authorization-code/callback',
  scope: 'openid profile'
});

app.use(session({
  secret: 'this-should-be-very-random',
  resave: true,
  saveUninitialized: false
}));
app.use(oidc.router);
app.get('/', (req, res) => {
  if (req.userinfo) {
    res.send(`Hello ${req.userinfo.name}! <a href="logout">Logout</a>`);
  } else {
    res.send('Please <a href="/login">login</a>');
  }
});
app.get('/protected', oidc.ensureAuthenticated(), (req, res) => {
  res.send('Top Secret');
});
app.get('/logout', (req, res) => {
  req.logout();
  res.redirect('/');
});
oidc.on('ready', () => {
  app.listen(3000, () => console.log('app started'));
});
oidc.on('error', err => {
  // An error occurred while setting up OIDC
});

ExpressOIDC API

new ExpressOIDC(config)

To configure your OIDC integration, create an instance of ExpressOIDC and pass options. Most apps will need this basic configuration:

const { ExpressOIDC } = require('@okta/oidc-middleware');

const oidc = new ExpressOIDC({
  issuer: YOUR_ISSUER,
  client_id: YOUR_CLIENT_ID,
  client_secret: YOUR_CLIENT_SECRET,
  redirect_uri: YOUR_REDIRECT_URI,
  scope: 'openid profile'
});

Required config:

  • issuer - The OIDC provider (e.g. https://YOUR_ORG.oktapreview.com/oauth2/default)
  • client_id - An id provided when you create an OIDC app in your Okta Org
  • client_secret - A secret provided when you create an OIDC app in your Okta Org
  • redirect_uri - The callback for your app. Locally, this is usually http://localhost:3000/authorization-code/callback. When deployed, this should be https://YOUR_PROD_DOMAIN/authorization-code/callback.

Optional config:

  • response_type - Defaults to code
  • scope - Defaults to openid, which will only return the sub claim. To obtain more information about the user, use openid profile. For a list of scopes and claims, please see Scope-dependent claims for more information.
  • routes - Allows customization of the generated routes. See Customizing Routes for details.
  • maxClockSkew - Defaults to 120. This is the maximum difference allowed between your server's clock and Okta's in seconds. Setting this to 0 is not recommended, because it increases the likelihood that valid jwts will fail verification due to nbf and exp issues.
  • timeout - Defaults to 10000 milliseconds. The HTTP max timeout for any requests to the issuer. If a timeout exception occurs you can catch it with the oidc.on('error', fn) handler.

oidc.router

This should be added to your express app to attach the login and callback routes:

const { ExpressOIDC } = require('@okta/oidc-middleware');
const express = require('express');

const app = express();
const oidc = new ExpressOIDC({ /* options */ });

app.use(oidc.router);

It's required in order for ensureAuthenticated and isAuthenticated to work and adds the following routes:

  • /login - redirects to the Okta sign-in page by default
  • /authorization-code/callback - processes the OIDC response, then attaches userinfo to the session

oidc.on('ready', callback)

The middleware must retrieve some information about your client before starting the server. You must wait until ExpressOIDC is ready to start your server.

oidc.on('ready', () => {
  app.listen(3000, () => console.log('app started'));
});

oidc.on('error', callback)

This is triggered if an error occurs while ExpressOIDC is trying to start.

oidc.on('error', err => {
  // An error occurred while setting up OIDC
});

oidc.ensureAuthenticated({ redirectTo?: '/uri' })

Use this to protect your routes. If not authenticated, this will redirect to the login route and trigger the authentication flow. If the request prefers JSON then a 401 error response will be sent.

app.get('/protected', oidc.ensureAuthenticated(), (req, res) => {
  res.send('Protected stuff');
});

The redirectTo option can be used to redirect the user to a specific URI on your site, after a successful authentication callback.

req.isAuthenticated()

This allows you to determine if a user is authenticated.

app.get('/', (req, res) => {
  if (req.isAuthenticated()) {
    res.send('Logged in');
  } else {
    res.send('Not logged in');
  }
});

req.logout()

This allows you to end the session.

app.get('/logout', (req, res) => {
  req.logout();
  res.redirect('/');
});

req.userinfo

This provides information about the authenticated user, and is obtained from the userinfo endpoint of the authorization server and depends on the scope requested (see scope option above):

app.get('/', (req, res) => {
  if (req.userinfo) {
    res.send(`Hi ${req.userinfo.sub}!`);
  } else {
    res.send('Hi!');
  }
});

Customization

Customizing Routes

If you need to modify the default login and callback routes, the routes config option is available.

const oidc = new ExpressOIDC({
  // ...
  routes: {
    login: {
      path: '/different/login'
    },
    callback: {
      path: '/different/callback',
      handler: (req, res, next) => {
        // Perform custom logic before final redirect, then call next()
      },
      defaultRedirect: '/home'
    }
  }
});
  • callback.defaultRedirect - Where the user is redirected to after a successful authentication callback, if no returnTo value was specified by oidc.ensureAuthenticated(). Defaults to /.
  • callback.failureRedirect - Where the user is redirected to after authentication failure, defaults to a page which just shows error message.
  • callback.handler - A function that is called after a successful authentication callback, but before the final redirect within your application. Useful for requirements such as conditional post-authentication redirects, or sending data to logging systems.
  • callback.path - The URI that this library will host the callback handler on. Defaults to /authorization-code/callback
  • login.path - The URI that redirects the user to the authorize endpoint. Defaults to /login.

Using a Custom Login Page

By default the end-user will be redirected to the Okta Sign-In Page when authentication is required, this page is hosted on your Okta Org domain. It is possible to host this experience within your own application by installing the Okta Sign-In Widget into a page in your application. Please refer to the test example file for an example of how the widget should be configured for this use case.

Once you have created your login page, you can use the viewHandler option to intercept the login page request and render your own custom page:


const oidc = new ExpressOIDC({
  { /* options */ }
  routes: {
    login: {
      viewHandler: (req, res, next) => {
        const baseUrl = url.parse(baseConfig.issuer).protocol + '//' + url.parse(baseConfig.issuer).host;
        // Render your custom login page, you must create this view for your application and use the Okta Sign-In Widget
        res.render('login', {
          csrfToken: req.csrfToken(),
          baseUrl: baseUrl
        });
      }
    }
  }
});

Extending the User

To add additional data about a user from your database, we recommend adding middleware to extend req.

const { ExpressOIDC } = require('@okta/oidc-middleware');
const express = require('express');
const session = require('express-session');

const app = express();
app.use(session({ /* options */ }));
const oidc = new ExpressOIDC({ /* options */ });
app.use(oidc.router);

function addUserContext(req, res, next) {
  if (!req.userinfo) return next();

  // request additional info from your database
  User.findOne({ id: req.userinfo.sub }, (err, user) => {
    if (err) return next(err);
    req.user = user;
    next();
  });
}

app.use(addUserContext);

{ /* options */ } // add other routes

oidc.on('ready', () => app.listen(3000));
oidc.on('error', err => console.log('could not start', err));

Using Proxy Servers

The underlying openid-client library can be configured to use the request library. Do this by adding these lines to your app, before you call new ExpressOIDC():

const Issuer = require('openid-client').Issuer;

Issuer.useRequest();

const oidc = new ExpressOIDC({
  ...
});

Once you have done that you can read the documentation on the request library to learn which environment variables can be used to define your proxy settings.