express-openid-connect and oidc-provider are both npm packages that facilitate OpenID Connect (OIDC) integration in Node.js applications, but they serve fundamentally different roles in the authentication architecture. express-openid-connect is a lightweight middleware designed for Express.js applications acting as OIDC relying parties (i.e., clients that consume identity from an external provider like Auth0, Okta, or Azure AD). In contrast, oidc-provider is a full-featured, spec-compliant OIDC identity provider implementation that enables you to build your own authorization server—handling token issuance, user consent flows, discovery endpoints, and more.
At first glance, both express-openid-connect and oidc-provider deal with OpenID Connect—but they occupy opposite ends of the authentication flow. Confusing them is like mixing up a door lock (express-openid-connect) with the entire key factory (oidc-provider). Let’s break down how they differ in practice.
express-openid-connect turns your Express app into an OIDC relying party (RP)—a client that trusts an external identity provider (IdP). Your app redirects users to the IdP (e.g., Auth0), receives ID tokens, and validates them. You never issue tokens yourself.
// express-openid-connect: Simple RP setup
const { auth } = require('express-openid-connect');
app.use(auth({
issuerBaseURL: 'https://your-tenant.auth0.com',
clientID: 'your-client-id',
secret: 'your-client-secret',
baseURL: 'https://your-app.com',
routes: { callback: '/callback' }
}));
app.get('/profile', (req, res) => {
// req.openid.user contains verified claims
res.json(req.openid.user);
});
oidc-provider, by contrast, lets you become the identity provider. You implement /authorize, /token, .well-known/openid-configuration, and all other OIDC endpoints. Clients (like SPAs or mobile apps) will redirect users to your server for login.
// oidc-provider: Minimal IdP setup
const Provider = require('oidc-provider');
const provider = new Provider('https://your-idp.com', {
clients: [{
client_id: 'spa-client',
client_secret: 'secret',
redirect_uris: ['https://client.com/callback'],
response_types: ['code']
}],
// You must implement interactions (login, consent)
interactionUrl(ctx) {
return `/interaction/${ctx.oidc.uid}`;
},
findAccount: async (ctx, id) => ({ accountId: id, claims: () => ({ sub: id }) })
});
app.use(provider.callback());
With express-openid-connect, your responsibilities are limited:
The library handles:
prompt=noneWith oidc-provider, you own the entire security surface:
Missing any of these correctly can lead to critical vulnerabilities like token leakage or account takeover.
express-openid-connect if:oidc-provider if:With express-openid-connect: Developers sometimes assume it handles authorization (it doesn’t—it only does authentication). You still need to enforce RBAC/ABAC in your routes using scopes or custom claims.
With oidc-provider: The biggest risk is incomplete implementation. For example, skipping PKCE enforcement for public clients or neglecting to validate redirect_uri strictly can enable open redirect attacks. The library provides hooks but won’t secure your app by default—you must wire everything correctly.
| Aspect | express-openid-connect | oidc-provider |
|---|---|---|
| Role | OIDC Relying Party (Client) | OIDC Identity Provider (Server) |
| Typical User | Web app needing login | Company building its own Auth0 |
| Setup Time | Minutes | Weeks to months |
| Security Surface | Small (delegates to IdP) | Large (you own all flows) |
| Spec Compliance | Consumes standards | Implements full OIDC/OAuth 2.0 specs |
Bottom Line: If your app needs to log users in, use express-openid-connect (or similar RP libraries). If you need to let other apps log users in via your system, consider oidc-provider—but only after evaluating managed alternatives like Auth0 Actions or Keycloak. Never roll your own IdP unless absolutely necessary; identity is notoriously hard to get right.
Choose oidc-provider only if you need to build and operate your own OpenID Connect identity provider—such as for white-label SSO, internal enterprise IAM systems, or compliance scenarios requiring full control over token issuance and user consent. It demands deep understanding of OAuth 2.0 and OIDC specs, including PKCE, DPoP, front/back-channel logout, and dynamic client registration. Avoid this if you can use a managed identity service; it’s overkill for standard client-side authentication needs.
Choose express-openid-connect when your application needs to authenticate users via an existing OIDC-compliant identity provider (such as Auth0, Google Identity Platform, or Microsoft Entra ID). It’s ideal for typical web apps or APIs that delegate authentication responsibility and require minimal setup—just configure issuer, client ID, and secret. This package handles session management, token validation, and secure redirects out of the box, making it perfect for teams prioritizing rapid integration without managing identity infrastructure.
This module provides an OAuth 2.0 (RFC 6749) Authorization Server with support for OpenID Connect (OIDC) and many other additional features and standards.
Table of Contents
The following specifications are implemented by oidc-provider (not exhaustive):
Note that not all features are enabled by default, check the configuration section on how to enable them.
RFC6749 - OAuth 2.0 & OIDC Core 1.0Discovery 1.0 & RFC8414 Authorization Server MetadataRP-Initiated Logout 1.0Back-Channel Logout 1.0RFC7009 - OAuth 2.0 Token RevocationRFC7636 - Proof Key for Code Exchange (PKCE)RFC7662 - OAuth 2.0 Token IntrospectionRFC8252 - OAuth 2.0 for Native Apps BCP (AppAuth)RFC8628 - OAuth 2.0 Device Authorization Grant (Device Flow)RFC8705 - OAuth 2.0 Mutual TLS Client Authentication and Certificate Bound Access Tokens (MTLS)RFC8707 - OAuth 2.0 Resource IndicatorsRFC9101 - OAuth 2.0 JWT-Secured Authorization Request (JAR)RFC9126 - OAuth 2.0 Pushed Authorization Requests (PAR)RFC9207 - OAuth 2.0 Authorization Server Issuer Identifier in Authorization ResponseRFC9449 - OAuth 2.0 Demonstration of Proof-of-Possession at the Application Layer (DPoP)RFC9701 - JWT Response for OAuth Token IntrospectionFAPI 1.0)FAPI 2.0)JARM)CIBA)Supported Access Token formats:
The following draft specifications are implemented by oidc-provider:
FAPI-CIBA) - Implementers Draft 01FAPI 2.0) - Implementers Draft 01Updates to draft specification versions are released as MINOR library versions,
if you utilize these specification implementations consider using the tilde ~ operator in your
package.json since breaking changes may be introduced as part of these version updates. Alternatively
acknowledge the version and be notified of breaking changes as part of
your CI.

Filip Skokan has certified that oidc-provider
conforms to the following profiles of the OpenID Connect™ protocol.
If you want to quickly add OpenID Connect authentication to Node.js apps, feel free to check out Auth0's Node.js SDK and free plan. Create an Auth0 account; it's free!
If you or your company use this module, or you need help using/upgrading the module, please consider becoming a sponsor so I can continue maintaining it and adding new features carefree. The only way to guarantee you get feedback from the author & sole maintainer of this module is to support the package through GitHub Sponsors.
oidc-provider can be mounted to existing connect, express, fastify, hapi, or koa applications, see how. The authorization server allows to be extended and configured in various ways to fit a variety of uses. See the documentation and example folder.
import * as oidc from "oidc-provider";
const provider = new oidc.Provider("http://localhost:3000", {
// refer to the documentation for other available configuration
clients: [
{
client_id: "foo",
client_secret: "bar",
redirect_uris: ["http://localhost:8080/cb"],
// ... other client properties
},
],
});
const server = provider.listen(3000, () => {
console.log(
"oidc-provider listening on port 3000, check http://localhost:3000/.well-known/openid-configuration",
);
});
External type definitions are available via DefinitelyTyped.
Collection of Community-maintained configuration use cases are in the Community Guides Discussions section
oidc-provider instances are event emitters, using event handlers you can hook into the various actions and i.e. emit metrics that react to specific triggers. See the list of available emitted event names and their description.
| Version | Security Fixes 🔑 | Other Bug Fixes 🐞 | New Features ⭐ |
|---|---|---|---|
| v9.x | Security Policy | ✅ | ✅ |
| v8.x | Security Policy | ❌ | ❌ |