Express OpenID Connect Middleware

raw JSON →
2.20.2 verified Thu Apr 23 auth: no javascript

express-openid-connect is an Express.js middleware designed to integrate OpenID Connect (OIDC) authentication into web applications, streamlining user login and session management. Currently at version 2.20.2, the library is actively maintained with a regular release cadence, frequently addressing bug fixes and introducing minor features. It abstracts away much of the complexity of OIDC flows, particularly when used with Auth0 as an identity provider, by handling authentication, logout, and session management automatically. Key differentiators include its focus on Express applications, deep integration capabilities with Auth0, and providing sensible defaults to secure web applications, while also offering extensive configuration options for advanced use cases. It ships with TypeScript types, enhancing developer experience for type-safe applications.

error invalid state
cause Typically occurs when the application runs over HTTP instead of HTTPS, or when the `baseURL` and configured Auth0 callback URLs do not match the application's actual origin.
fix
Ensure your application is accessible via HTTPS, even in development. Verify that config.baseURL in your code and 'Allowed Callback URLs'/'Allowed Logout URLs' in your Auth0 application settings precisely match your application's origin (e.g., https://localhost:3000).
error Missing transaction cookie
cause The OIDC flow relies on a state cookie, which may be missing due to browser security restrictions (e.g., `SameSite` policy), interference from proxies, or an improperly configured custom session store.
fix
Check your browser's console for any cookie-related warnings. Ensure your application uses HTTPS. If using a custom session store, verify its get() method correctly retrieves the state. Upgrade to express-openid-connect@2.20.2 or newer for fixes related to missing transaction cookies.
error JsonWebToken Signature Algorithm must be RS256
cause This error occurs during token validation if the Auth0 application's 'JsonWebToken Signature Algorithm' is not set to `RS256`, or if 'OIDC Conformant' is not enabled.
fix
In your Auth0 Dashboard, navigate to your application's 'Settings', then 'Advanced Settings' -> 'OAuth' tab. Set 'JsonWebToken Signature Algorithm' to RS256 and ensure 'OIDC Conformant' is enabled.
error TypeError: Joi.binary is not a function
cause This issue arises from compatibility problems with certain validation libraries (like Joi) in specific environments, such as Cloudflare Workers, where `Joi.binary()` might be unavailable or behave unexpectedly.
fix
This specific issue was addressed in express-openid-connect@2.20.0. Ensure you are using v2.20.0 or a later version of the library. If the problem persists in a unique environment, consult the library's compatibility notes or report an issue.
breaking The `secret` configuration variable is critical for session security and requires a minimum length to prevent replay attacks and session hijacking.
fix Ensure the `secret` value in your configuration is a long, random string, preferably 32 characters or more, and stored securely (e.g., via environment variables).
gotcha Applications using this library must run over HTTPS, even during local development, to prevent 'invalid state' errors and ensure proper cookie handling due to modern browser security policies.
fix Configure your development environment to use HTTPS (e.g., with `ngrok`, `mkcert`, or a local proxy) and ensure your `baseURL` matches your HTTPS URL (e.g., `https://localhost:3000`).
breaking The Auth0 application settings for 'JsonWebToken Signature Algorithm' must be set to `RS256`, and 'OIDC Conformant' must be enabled. Incorrect settings can lead to token validation failures and authentication issues.
fix In the Auth0 Dashboard, navigate to your application's 'Settings', then 'Advanced Settings' -> 'OAuth' tab. Set 'JsonWebToken Signature Algorithm' to `RS256` and ensure 'OIDC Conformant' is enabled.
gotcha Using `agent-base` with certain proxy or network configurations might cause connectivity issues during OIDC discovery or token exchange.
fix Review the `express-openid-connect` FAQ for potential workarounds or consider alternative HTTP agents if encountering proxy-related connection problems.
breaking Custom asynchronous session store methods (e.g., `get`, `set`, `destroy`) must correctly handle Node.js callbacks or return promises. Incorrect promisification or handling of `async` functions can lead to session data inconsistencies or failures.
fix Ensure custom session store implementations consistently return promises for `async` operations or adhere to standard Node.js callback patterns that the library can properly promisify. Consult the documentation for `util-promisify` if using custom stores and encountering issues.
npm install express-openid-connect
yarn add express-openid-connect
pnpm add express-openid-connect

This quickstart initializes an Express application with OpenID Connect authentication using `express-openid-connect`. It demonstrates basic login, logout, and a protected profile route, requiring environment variables for Auth0 configuration.

import express from 'express';
import { auth, requiresAuth } from 'express-openid-connect';
import dotenv from 'dotenv';

dotenv.config(); // Load environment variables from .env file

const app = express();
const port = process.env.PORT || 3000;

const config = {
  authRequired: false,
  auth0Logout: true,
  secret: process.env.SECRET ?? 'a-very-long-random-string-that-is-at-least-32-characters-long',
  baseURL: process.env.BASE_URL ?? `http://localhost:${port}`,
  clientID: process.env.CLIENT_ID ?? 'YOUR_AUTH0_CLIENT_ID',
  issuerBaseURL: process.env.ISSUER_BASE_URL ?? 'https://YOUR_AUTH0_DOMAIN',
  // Uncomment and configure a session store for production environments
  // session: {
  //   store: new MemoryStore({ checkPeriod: 86400000 })
  // }
};

// Attach /login, /logout, and /callback routes to the baseURL
app.use(auth(config));

// Basic route, checks if user is authenticated
app.get('/', (req, res) => {
  res.send(
    `<h1>Welcome</h1><p>${
      req.oidc.isAuthenticated() ? 'Logged in' : 'Logged out'
    }</p><a href="/login">Login</a> | <a href="/profile">Profile</a> | <a href="/logout">Logout</a>`
  );
});

// The /profile route requires authentication
app.get('/profile', requiresAuth(), (req, res) => {
  res.send(
    `<h2>User Profile</h2><pre>${JSON.stringify(req.oidc.user, null, 2)}</pre><a href="/">Home</a>`
  );
});

// Example of a public route that does not require authentication
app.get('/public', (req, res) => {
  res.send(`
    <h1>Public Page</h1>
    <p>User is ${req.oidc.isAuthenticated() ? 'authenticated' : 'not authenticated'}.</p>
    <a href="/">Home</a>
  `);
});

app.listen(port, () => {
  console.log(`Server running on http://localhost:${port}`);
  console.log('Remember to set ISSUER_BASE_URL, CLIENT_ID, BASE_URL, and SECRET environment variables.');
  console.log('Also, configure "Allowed Callback URLs" and "Allowed Logout URLs" in Auth0 to match your BASE_URL.');
});