express-openid-connect 和 oidc-provider 都是 Node.js 生态中处理 OpenID Connect (OIDC) 协议的核心库,但它们的定位截然不同。express-openid-connect 是一个客户端(Relying Party)中间件,旨在帮助 Express 应用快速集成现有的身份认证服务(如 Auth0、Okta),实现用户登录和会话管理。而 oidc-provider 是一个服务端(OpenID Provider)库,允许开发者构建自己的身份认证服务器,为其他应用提供登录能力。理解这一根本区别是架构选型的关键。
在 Node.js 后端开发中,处理身份认证通常面临两个截然不同的方向:是接入现有的认证服务,还是构建自己的认证中心?express-openid-connect 和 oidc-provider 分别代表了这两个方向的行业标准解决方案。虽然它们都基于 OpenID Connect 协议,但它们在应用架构中的角色完全相反。让我们从实际工程角度深入对比。
express-openid-connect 是一个依赖方 (Relying Party, RP) 库。
// express-openid-connect: 作为客户端集成认证
const { auth } = require('express-openid-connect');
app.use(auth({
auth0Logout: true,
baseURL: 'https://your-app.com',
clientID: 'YOUR_CLIENT_ID',
issuerBaseURL: 'https://your-tenant.auth0.com'
}));
// 保护路由
app.get('/profile', requiresAuth(), (req, res) => {
res.send(req.oidc.user); // 直接获取用户信息
});
oidc-provider 是一个开放提供商 (OpenID Provider, OP) 库。
// oidc-provider: 构建自己的认证服务器
const Provider = require('oidc-provider');
const provider = new Provider('https://your-idp.com', {
clients: [
{
client_id: 'client-1',
client_secret: 'secret',
redirect_uris: ['https://app-1.com/callback']
}
],
// 配置密钥对用于签名 Token
jwks: {
keys: [{
kty: 'RSA',
kid: 'my-key',
n: '...',
e: 'AQAB',
d: '...',
p: '...',
q: '...'
}]
}
});
app.use(provider.app);
express-openid-connect 追求开箱即用。
// 配置会话和授权参数
app.use(auth({
session: {
duration: 3600, // 会话有效期 1 小时
absoluteDuration: 7200
},
authorizationParams: {
response_type: 'code',
scope: 'openid profile email'
}
}));
oidc-provider 要求深度定制。
// 自定义交互策略:决定何时跳过登录
const policy = provider.interactionPolicy;
policy.add(new policy.Check('skip_login', (ctx) => {
// 如果已有有效会话,跳过登录页
return ctx.session?.accountId;
}), true);
express-openid-connect 依赖加密会话 Cookie。
// 配置会话密钥(生产环境必须使用环境变量)
app.use(auth({
secret: process.env.SESSION_SECRET,
auth0Logout: true,
// 启用刷新令牌旋转
tokenEndpointParams: {
token_endpoint_auth_method: 'client_secret_post'
}
}));
oidc-provider 提供细粒度的安全控制。
// 配置 Token 格式和安全策略
const provider = new Provider('https://idp.com', {
features: {
encryption: { enabled: true }, // 启用 ID Token 加密
mTLs: { enabled: false }
},
// 自定义 Token 过期时间
expires: {
AccessToken: 3600,
RefreshToken: 1209600
}
});
express-openid-connect 流程是固定的。
// 触发登录流程(自动处理重定向)
app.get('/login', (req, res) => {
res.oidc.login({
returnTo: '/dashboard',
authorizationParams: { prompt: 'login' } // 强制重新登录
});
});
oidc-provider 流程是可编程的。
// 自定义渲染登录页面(伪代码示例)
provider.renderInteraction = async (ctx, next) => {
// 这里可以接入你自己的 UI 框架渲染登录表单
await renderLoginView(ctx.req, ctx.res, ctx.oidc);
};
express-openid-connect 易于水平扩展。
// 配合 Redis 存储会话以支持多实例
app.use(auth({
session: {
store: new RedisStore({ client: redisClient })
}
}));
oidc-provider 需要独立部署。
// 配置持久化适配器(必须实现数据库存储)
const adapter = (model) => {
return {
upsert: async (id, payload) => { /* 写入 DB */ },
find: async (id) => { /* 读取 DB */ },
// ... 其他 CRUD 方法
};
};
const provider = new Provider('https://idp.com', { adapter });
尽管角色不同,两者都严格遵循 OpenID Connect 核心规范。
.well-known/openid-configuration)。// 两者都兼容的标准发现端点访问
// 客户端发现提供商配置
const config = await fetch('https://idp.com/.well-known/openid-configuration');
// 服务端自动暴露该端点
// oidc-provider 默认在 /.well-known/openid-configuration 提供配置
| 特性 | express-openid-connect | oidc-provider |
|---|---|---|
| 角色 | 🧑💻 客户端 (Relying Party) | 🏢 服务端 (Identity Provider) |
| 主要用途 | 保护你的应用,接入外部登录 | 构建认证中心,让别人接入你 |
| 用户数据存储 | ❌ 不存储 (依赖外部) | ✅ 需自行实现存储 |
| 配置复杂度 | ⭐ 低 (配置文件为主) | ⭐⭐⭐⭐⭐ 高 (需实现逻辑) |
| 适用场景 | 业务系统、SaaS、后台管理 | 统一身份认证平台、IAM 系统 |
| 维护成本 | 低 (跟随库更新) | 高 (需关注安全补丁/协议) |
选择 express-openid-connect 的情况:
你正在开发一个普通的 Web 应用,需要用户登录功能,但不想自己处理密码存储、邮箱验证、多因素认证等复杂的安全问题。你愿意使用 Auth0、Okta 或自建的关键cloak 作为身份源。这是90% 业务应用的最佳选择。
选择 oidc-provider 的情况:
你正在构建一个平台型产品,需要为多个子系统或第三方合作伙伴提供统一的账号体系。你有合规需求(如数据必须留在内网),无法使用云厂商的认证服务。你有足够的资源维护一个高可用的认证服务团队。这是构建 IAM/IDM 系统的基础设施选择。
最终建议:不要混淆两者的角色。如果你的需求是“让用户登录我的网站”,请用 express-openid-connect。如果你的需求是“让我的网站成为登录入口”,请用 oidc-provider。在微服务架构中,通常会看到两者共存:oidc-provider 构建中央认证服务,而各个微服务使用 express-openid-connect 进行接入。
选择 oidc-provider 如果你需要构建一个身份认证平台,让其他第三方应用或内部微服务通过你的系统进行登录。它适合需要完全控制认证流程、支持自定义 Grant 类型或合规性要求极高的场景。如果你打算替代 Auth0 或 Okta 自建 IdP,这是目前 Node.js 生态中最成熟的标准实现方案。
选择 express-openid-connect 如果你的目标是保护自己的 Express 应用,并希望用户通过现有的身份提供商(如 Auth0、Google、Azure AD)进行登录。它适合大多数需要快速集成单点登录 (SSO) 的业务系统,配置简单且内置了会话管理。如果你不需要自己管理用户密码或颁发 Token,只需验证用户身份,这是最佳选择。
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)FAPI 2.0)JARM)CIBA)Supported Access Token formats:
The following specifications and drafts are implemented as experimental features:
FAPI-CIBA) - Implementers Draft 01CIMD) - Draft 01Updates to experimental feature specification versions are released as MINOR library versions,
if you utilize these features 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 | ❌ | ❌ |