Lazy loaded image
Lazy loaded imagenCalendar 单点登录之 Dex 统一退出
字数 1063阅读时长≈ 3 分钟
2025-6-2
type
status
date
slug
summary
category
tags
create_time
Jun 2, 2025 04:55 PM
icon
password
my_create_time

📌 背景

nCalendar 项目中,统一认证采用 Dex 作为 OpenID Connect Provider,多个系统通过 Dex 实现单点登录:
  • 例如:nCalendar 管理后台、订阅配置界面、用户门户等
  • 每个系统作为一个 OIDC 客户端,通过授权码模式登录
  • 用户首次登录任一系统后,其余系统可自动完成无感登录(silent login)
问题出现:
用户在某系统点击“退出登录”按钮,仅退出了该前端应用,但 Dex 仍保存全局会话 Cookie,用户访问其他系统时仍视为已登录。
PS:其实 Dex 也没实现全局 Cookie,是我自己实现的一套。。。

🧩 使用场景

  • 用户访问多个基于 Dex 登录的子系统
  • 希望点击任一“退出登录”按钮后,同时退出 Dex 和所有已登录系统
  • 提升用户安全体验,尤其在共享电脑、公用设备上的使用场景

✅ 实现目标

用户登出某个子系统后,应同时触发 Dex 的全局会话清除,其他系统重新访问将跳转登录页。

🖼️ 退出流程图

notion image

🛠️ 流程分步详解

下面详细分解统一登出流程的每一个关键步骤:

1️⃣ 用户点击“退出登录”按钮

用户在管理后台点击退出按钮后,前端不会直接跳转,而是调用应用后端的 /logout 接口。
后端进行以下操作:
  • 清理当前系统的 session、token 等本地登录状态;
  • 构建指向 Dex 的退出 URL,通常包括以下参数:
    • id_token_hint: 当前会话的 ID Token,用于标识要注销的会话;
    • post_logout_redirect_uri: Dex 完成登出后应跳转回的地址;
    • state: 可选参数,用于防止 CSRF 攻击。

2️⃣ 自定义 Dex 的隐藏 logout 页面和接口

Dex 默认未实现 RP-Initiated Logout,因此我们需手动实现:
  • 一个“隐藏的登出页面”,例如 /dex/logout
  • 页面内通过 JavaScript 发起对 Dex 后端 /logout 接口的请求
  • 可选:根据 OpenID Connect 标准将登出 URL 通过 Discover 配置暴露,例如:
这样,前端应用在实现中也可以动态发现并获取登出接口。

3️⃣ Dex 服务端执行登出操作

在隐藏页面中调用 Dex 后端接口时,会完成如下操作:
  • 校验 id_token_hint 的合法性;
  • 清除 Dex 维护的“全局 Cookie”(我们自定义实现的);
  • 依次回调所有注册应用的登出接口,确保每个子系统都能同步清理本地状态;
    • 比如:POST 请求到 https://admin.ncalendar.com/logout, https://portal.ncalendar.com/logout
这一机制参考了 OIDC 的 Front-Channel 或 Back-Channel Logout 实现模式。

4️⃣ Dex 构建跳转回应用的重定向地址

Dex 后端完成登出流程后,根据 post_logout_redirect_uri 构建返回地址。
此参数由初始请求者传入,Dex 验证合法性后返回给前端隐藏页面。

5️⃣ Dex 隐藏页面重定向到应用首页

隐藏页面拿到重定向地址后,前端自动跳转回原始应用首页,至此用户“统一登出流程”圆满完成。

✅ 总结

虽然 Dex 目前尚不支持原生的统一登出与全局 Cookie 管理,但通过自定义隐藏页面、会话清理接口及各子系统回调机制,我们仍可实现:
  • 统一登录体验(SSO)
  • 统一登出体验(Single Logout)
  • 增强安全性,保障用户数据不被滥用
这套方案不仅适用于 nCalendar,也为使用 Dex 构建 SSO 架构的其他项目提供了参考。

📎 参考文章

 
💡
有关文章的任何疑问,欢迎您在底部评论区留言,一起交流~
若文章对您有帮助,欢迎 请我喝杯咖啡~
上一篇
Nginx+ACME服务器搭建
下一篇
nCalendar 单点登录之 Dex 全流程解析

评论
Loading...