Express OpenID Connect Middleware
raw JSON →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.
Common errors
error invalid state ↓
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 ↓
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 ↓
RS256 and ensure 'OIDC Conformant' is enabled. error TypeError: Joi.binary is not a function ↓
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. Warnings
breaking The `secret` configuration variable is critical for session security and requires a minimum length to prevent replay attacks and session hijacking. ↓
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. ↓
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. ↓
gotcha Using `agent-base` with certain proxy or network configurations might cause connectivity issues during OIDC discovery or token exchange. ↓
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. ↓
Install
npm install express-openid-connect yarn add express-openid-connect pnpm add express-openid-connect Imports
- auth wrong
const auth = require('express-openid-connect');correctimport { auth } from 'express-openid-connect'; - requiresAuth wrong
app.use(auth.requiresAuth());correctimport { requiresAuth } from 'express-openid-connect'; - isAuthenticated wrong
import isAuthenticated from 'express-openid-connect';correctimport { isAuthenticated } from 'express-openid-connect';
Quickstart
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.');
});