FEATURED · 精选文章

Authelia OpenID Connect 1.0 与 Express.js 集成实战:基于 express-openid-connect 实现 SSO 登录

发布时间 / 2026/9/11 23:44:42
来源 / 创域科博编辑部
栏目 / 资讯中心
Authelia OpenID Connect 1.0 与 Express.js 集成实战:基于 express-openid-connect 实现 SSO 登录 Authelia OpenID Connect 1.0 与 Express.js 集成实战基于 express-openid-connect 实现 SSO 登录【免费下载链接】autheliaThe Single Sign-On Multi-Factor portal for web apps. OpenID Certified™ and Post-Quantum Cryptography Ready.项目地址: https://gitcode.com/GitHub_Trending/au/authelia本指南以 Authelia 官方集成文档docs/content/integration/openid-connect/clients/expressjs/index.md为主体完整讲解如何将 Authelia 作为 OpenID Connect 1.0 提供方OP与基于 Express.js 与express-openid-connect中间件的 Node.js 应用对接实现安全的单点登录SSO。读完本文你将掌握 Authelia 侧注册客户端含 PKCE、Pushed Authorization Requests 等安全强化的配置写法、应用侧中间件接入与令牌/用户信息消费的完整落地步骤并理解其背后的授权码流原理。测试版本与适用范围该集成方案在以下版本组合上经过了验证Autheliav4.38.0关联文档 中标注的测试版本Express.js配合express与express-openid-connectAuth0 提供的 OpenID Connect Relying Party 中间件库使用这是一个开发者指南适用于从零构建自己的开放应用同时由于许多应用会复用express-openid-connect这类库本文的配置思路对这些应用同样具有参考价值。该集成由社区提供支持文档 frontmatter 中support.level: community。前提假设本文示例基于以下假设值展开在官方文档站点中这些值可通过文档变量自动替换此处采用其默认值配置项假设值应用根 URLApplication Root URLhttps://express.example.com/Authelia 根 URLAuthelia Root URLhttps://auth.example.com/Client IDexpressjs-exampleClient Secretinsecure_secret注意insecure_secret等值仅用于演示严禁直接用于生产环境详见下文开始前的注意事项。开始前的注意事项原文档通过{{% oidc-common %}}短代码引入了一段所有 OIDC 客户端集成指南共用的前置阅读内容其实现位于 docs/layouts/_shortcodes/oidc-common.html其中针对client_id与client_secret提出了若干必须遵守的硬性约束client_id必须是每个客户端唯一的。文档中的expressjs-example仅为便于阅读和演示生产环境不应直接使用应参考 OpenID Connect 常见问题 中如何生成客户端标识或密钥的说明官方建议 64 个随机字符。client_id只能包含 [RFC3986 非保留字符]且长度不得超过 100 个字符与 客户端配置文档 中的校验规则一致。client_secret可以明文形式存储在 Authelia 配置中但该行为已被弃用未来不保证继续支持。官方强烈建议以哈希形式存储本文示例即采用 PBKDF2-SHA512 哈希。当密钥以哈希形式存储时过高的哈希成本可能导致客户端请求超时必要时需参考常见问题文档中的调整工作因子说明进行调优。配置示例仅包含客户端注册片段你还必须同时配置 OpenID Connect 1.0 提供方配置 中的必需项并且熟悉 客户端配置文档 中的其他可用选项。第一步在 Authelia 中注册 OIDC 客户端在 Authelia 的configuration.yml中为 Express.js 应用注册如下客户端。示例中除注释外省略了提供方Provider的其他必备配置完整内容可参考仓库根目录的 config.template.yml 与 提供方配置文档identity_providers: oidc: ## The other portions of the mandatory OpenID Connect 1.0 configuration go here. clients: - client_id: expressjs-example client_name: Express.js App client_secret: $pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng # The digest of insecure_secret. public: false authorization_policy: two_factor require_pkce: true pkce_challenge_method: S256 require_pushed_authorization_requests: true redirect_uris: - https://express.example.com/callback scopes: - openid - profile - email - groups response_types: - code grant_types: - authorization_code access_token_signed_response_alg: none userinfo_signed_response_alg: none token_endpoint_auth_method: client_secret_basic关键参数逐项解析以下解释均以 客户端配置文档 中的权威说明为依据client_id必填客户端唯一标识必须与应用侧配置完全一致不超过 100 字符、仅含 RFC3986 非保留字符。client_name可选默认同client_id显示在 Authelia 用户界面中的友好名称。client_secret条件必填Authelia 与应用共享的密钥。此处存储的是明文insecure_secret的 PBKDF2-SHA512 哈希$pbkdf2-sha512$310000$...。机密型客户端必须提供若使用公钥类认证方式或公开客户端类型public: true则无需/必须为空。public: false声明为机密型confidential客户端。依据 RFC6749 Section 2.1机密型客户端能够安全保存凭据默认值为false。authorization_policy: two_factor默认two_factor该客户端的授权策略可选one_factor、two_factor或提供方中通过authorization_policies自定义的策略。注意此策略仅作用于授权请求与 Authelia 的 访问控制规则 是两套独立机制不应混淆差异原因详见 OIDC 常见问题 与 ADR1。require_pkce: true强制该客户端使用 PKCERFC7636。可对全部客户端全局强制对应提供方配置中的enforce_pkce选项。pkce_challenge_method: S256强制使用S256挑战方法同时会隐式启用require_pkce。有效值为空字符串、plain、S256强烈建议使用S256code_challenge是code_verifier的 SHA-256 摘要的 Base64URL 编码可缓解授权码拦截攻击。require_pushed_authorization_requests: true强制该客户端走 Pushed Authorization RequestsPARRFC9126 流程。PAR 端点要求与令牌端点相同的客户端认证、必须使用 POST 与application/x-www-form-urlencoded且只能在后信道发起能显著提升授权流程对钓鱼攻击的抵抗力。需注意大多数客户端不支持此选项express-openid-connect支持这也是本文启用它的原因全局强制对应提供方配置中的pushed_authorizations.enforce。redirect_uris必填合法回调 URI 列表大小写敏感scheme 必须是http或https不在列表中的回调会被视为不安全并拒绝授权。scopes允许该客户端消费的 scope 列表默认openid,groups,profile,email应匹配应用实际所需的 claimsscope 定义详见 OpenID Connect 1.0 Claims 文档。response_types: [code]仅允许授权码流。官方明确建议只使用code其余响应类型安全性较差。grant_types: [authorization_code]允许使用的授权类型默认即为authorization_code。access_token_signed_response_alg: none与userinfo_signed_response_alg: none两者的默认值都是none即 Access Token 与 UserInfo 响应均以明文 JSON 形式返回UserInfo 响应类型为application/json; charsetutf-8。此处显式写出是为了表达配置意图。若改为其他算法如RS256则 Access Token 会按 RFC9068。token_endpoint_auth_method: client_secret_basic客户端在令牌端点使用的认证方式机密型客户端默认即client_secret_basic通过 HTTP Basic Auth Scheme 提交密钥其他可选值包括client_secret_post、client_secret_jwt、private_key_jwt、none。第二步初始化 Express.js 项目执行以下命令创建项目目录、初始化package.json并安装两个依赖包mkdir authelia-example cd authelia-example npm init -y npm install express express-openid-connect其中express是 Web 框架express-openid-connect是负责与 OpenID Connect 提供方交互的认证中间件。第三步编写应用代码server.js下面的示例假设 Node 服务部署在反向代理之后由代理负责https://express.example.com的 TLS 终止。use strict; const express require(express); const { auth, requiresAuth } require(express-openid-connect); const { randomBytes } require(crypto); const app express(); app.use( auth({ authRequired: false, baseURL: ${process.env.APP_BASE_URL || https://express.example.com}, secret: process.env.SESSION_ENCRYPTION_SECRET || randomBytes(64).toString(hex), clientID: process.env.OIDC_CLIENT_ID || expressjs-example, clientSecret: process.env.OIDC_CLIENT_SECRET || insecure_secret, clientAuthMethod: process.env.OIDC_CLIENT_AUTH_METHOD || client_secret_basic, issuerBaseURL: process.env.OIDC_ISSUER || https://auth.example.com, pushedAuthorizationRequests: toBoolean(process.env.OIDC_PUSHED_AUTHORIZATION_REQUESTS, true), authorizationParams: { response_type: code, scope: process.env.OIDC_SCOPE || openid profile email groups, }, }) ); app.get(/, requiresAuth(), (req, res) { req.oidc.fetchUserInfo().then((userInfo) { const data JSON.stringify( { accessToken: req.oidc.accessToken, refreshToken: req.oidc.refreshToken, idToken: req.oidc.idToken, claims: { id_token: req.oidc.idToken, userinfo: userInfo, }, scopes: req.oidc.scope, }, null, 2); res.send(html langenbodyprecode${data}/code/pre/body/html); }); }); app.listen(3000, function () { console.log(Listening on port 3000) }); function toBoolean(value, defaultValue) { switch (value) { case true: case TRUE: case 1: return true case false: case FALSE: case 0: return false default: return defaultValue } }代码要点解读auth()中间件挂载后负责发现提供方元数据、发起授权请求、处理回调并建立会话。配置项通过环境变量注入并带有默认值便于本地快速启动。authRequired: false不强制所有路由都要求认证允许将/之外的路由按需保护。baseURL应用自身的根 URLexpress-openid-connect会据此构造回调地址即 Authelia 侧注册的https://express.example.com/callback。secret会话加密密钥。示例中若未设置SESSION_ENCRYPTION_SECRET会用crypto.randomBytes(64)生成一个每次启动都不同的随机值——这意味着重启后会话失效生产环境务必通过环境变量固定该值。issuerBaseURLOpenID Connect 提供方Authelia的根 URL即https://auth.example.com。中间件会通过其/.well-known/openid-configuration发现端点详见 集成简介 中的端点实现表。pushedAuthorizationRequests是否使用 PAR 流程与 Authelia 侧require_pushed_authorization_requests: true对应。若 Authelia 强制要求 PAR 而客户端未启用授权请求将被拒绝。authorizationParams.response_type与scope与 Authelia 侧注册的response_types、scopes保持一致。requiresAuth()路由守卫使/路由在未认证时自动重定向到 Authelia 登录页。req.oidc.fetchUserInfo()在认证后调用 Authelia 的 UserInfo 端点/api/oidc/userinfo见 集成简介获取用户信息与 ID Token 中的 claims 一并展示在页面上。toBoolean()辅助函数将字符串形式的环境变量如true/1转换为布尔值无法识别时回退到默认值。第四步配置环境变量标准方式.env 或导出环境变量APP_BASE_URLhttps://express.example.com # SESSION_ENCRYPTION_SECRET OIDC_ISSUERhttps://auth.example.com OIDC_CLIENT_IDexpressjs-example OIDC_CLIENT_SECRETinsecure_secret OIDC_PUSHED_AUTHORIZATION_REQUESTStrue OIDC_CLIENT_AUTH_METHODclient_secret_basic OIDC_SCOPEopenid profile email groups各变量的作用与取值约定环境变量作用对应 Authelia 配置APP_BASE_URL应用根 URL用于构造回调地址redirect_uris的 originSESSION_ENCRYPTION_SECRET会话加密密钥生产必填—应用侧OIDC_ISSUER提供方根 URLIssuer提供方issuerOIDC_CLIENT_ID客户端标识client_idOIDC_CLIENT_SECRET客户端密钥需为明文供应用侧使用client_secret对应的明文OIDC_PUSHED_AUTHORIZATION_REQUESTS是否启用 PARrequire_pushed_authorization_requestsOIDC_CLIENT_AUTH_METHOD令牌端点认证方式token_endpoint_auth_methodOIDC_SCOPE请求的 scope 列表scopes注意Authelia 配置中存储的是insecure_secret的哈希而应用侧OIDC_CLIENT_SECRET需要使用该密钥的明文。二者是同一密钥的两种存储形态必须严格对应。Docker Compose 方式若通过 Docker Compose 部署可按下述方式注入services: expressjs-example: environment: APP_BASE_URL: https://express.example.com # SESSION_ENCRYPTION_SECRET: OIDC_ISSUER: https://auth.example.com OIDC_CLIENT_ID: expressjs-example OIDC_CLIENT_SECRET: insecure_secret OIDC_PUSHED_AUTHORIZATION_REQUESTS: true OIDC_CLIENT_AUTH_METHOD: client_secret_basic OIDC_SCOPE: openid profile email groups集成背后的协议流程从 OpenID Connect 1.0 集成简介 可以看出本示例实际上组合了以下三条安全机制理解它们有助于排查集成问题授权码流Authorization Code Flow客户端以response_typecode发起授权请求Authelia 认证用户后经redirect_uri返回授权码客户端再以client_secret_basic认证方式在令牌端点/api/oidc/token兑换 Access Token / Refresh Token / ID Token。Authelia 对code响应类型默认支持form_post与query两种响应模式。PKCERFC7636即使code流本身安全Authelia 仍通过require_pkce: true与pkce_challenge_method: S256强制客户端证明对code_verifier的占有进一步缓解授权码被拦截/重放的风险。Pushed Authorization RequestsRFC9126require_pushed_authorization_requests: true要求授权参数先通过后信道 POST 到 PAR 端点/api/oidc/pushed-authorization-request返回request_uri后再携带其访问授权端点。由于 PAR 端点需要与令牌端点相同的客户端认证第三方无法伪造授权请求。这三项均属于 集成简介 中安全一节推荐的安全加固手段Authelia 还支持 OAuth 2.0 Authorization Server Issuer IdentificationRFC9207与 JARM 等更强的校验方式但express-openid-connect可能不支持需以客户端能力为准。安全建议与生产落地要点替换演示凭据expressjs-example/insecure_secret仅用于演示。生产环境应按 常见问题文档 中的方法生成随机 Client ID 与 Client Secret并将后者以哈希形式写入 Authelia 配置可通过 Authelia 提供的哈希生成命令完成。固定会话密钥必须显式设置SESSION_ENCRYPTION_SECRET避免依赖每次启动随机生成的密钥导致会话频繁失效。保持策略一致应用侧与 Authelia 侧的response_type、scope、client_auth_method、PAR 开关必须严格对应任何一侧收紧而另一侧未同步都会导致授权或令牌兑换失败。TLS 前置示例假定反向代理已为https://express.example.com终止 TLS回调 URI 必须与APP_BASE_URL同源且与 Authelia 注册的redirect_uris完全一致大小写敏感。理解访问控制边界客户端的authorization_policy只决定 Authelia 侧授权请求的强度应用自身的业务访问控制仍需在 Express.js 内通过requiresAuth()等机制实现。延伸阅读OpenID Connect 1.0 集成简介端点实现、响应类型/模式、客户端认证方式、PAR 与 PKCE 原理的完整说明OpenID Connect 1.0 客户端配置本文所有客户端参数的权威参考OpenID Connect 1.0 提供方配置提供方必需项、enforce_pkce、pushed_authorizations等全局选项OpenID Connect 常见问题Client ID/Secret 生成、哈希存储与工作因子调优config.template.yml仓库自带的完整配置模板【免费下载链接】autheliaThe Single Sign-On Multi-Factor portal for web apps. OpenID Certified™ and Post-Quantum Cryptography Ready.项目地址: https://gitcode.com/GitHub_Trending/au/authelia创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻