nCalendar 单点登录之 Dex 全流程解析

🧭 前言

上一篇《nCalendar 单点登录之 Dex 入门篇》大概介绍了 nCalendar 为什么要使用 Dex 以及 Dex 的一些基础概念,本篇开始实操,介绍实际的对接登录流程。

PS:nCalendar 目前已完成了对接,欢迎大家体验。官网地址:https://ncalendar.lusyoe.com

🖼️ 登录流程图

🛠️ 流程分步详解

下面我们分步骤解析 Dex 实现 SSO 登录的核心流程。

1️⃣ 客户端构造授权请求 URL

用户点击首页的登录按钮后,由客户端构建一个授权请求的URL,如上流程图所示:

1
2
3
4
5
6
7
https://auth.lusyoe.com/auth/<connector_id>?client_id=<client_id>
&redirect_uri=<回调地址>
&response_type=code
&scope=openid+profile+email
&state=<原始页面或临时信息>
&nonce=<防重放>
&connector_id=<可选当有多个connector时, 如github需要传入>

PS:这里 ncalendar 是自己实现了一套 connector,在里面处理登录/注册等逻辑。

2️⃣ Dex 跳转到 Connector 登录页

Dex 会根据 /auth/<connector_id> 中的 connector 设置,调用该 Connector 的 LoginURL() 方法,并生成登录链接。

PS:这里最好是自定义一个登录页面,原生自带的实在是太丑了。

3️⃣ 用户登录后回调 Dex 的 /callback

成功登录后,用户会被重定向回 Dex 的 /callback

注意:第一次回调的是自身的/callback,而不是第三方服务的。

在该 /callback 中又会回调自定义 connector 的 callback,用于确认是否真的登录成功,并获取用户个人信息如:用户名、邮箱等,根据这些信息再生成 OAuth2 授权码(Authorization Code),这个 code 码非常的关键,下一步需要通过这个码来获取token。

4️⃣ Dex 携带 code 跳转到客户端

Dex 完成认证后,会重定向到 redirect_uri,并携带授权码:

1
https://auth.lusyoe.com/auth/callback?code=xxx&state=yyy

5️⃣ 客户端使用 code 向 Dex 请求 id_token

服务端拿到 code 后,发送请求到 Dex的 /token

1
2
3
4
5
6
7
8
POST /token
Content-Type: application/x-www-form-urlencoded

client_id=ncalendar
client_secret=xxx
code=abc123
grant_type=authorization_code
redirect_uri=https://ncalendar.lusyoe.com/auth/callback

Dex 返回 token:

1
2
3
4
5
6
7
{
"access_token": "…",
"id_token": "…",
"refresh_token": "…",
"expires_in": 3600,
"token_type": "Bearer"
}

6️⃣ 客户端使用 /keys 校验 token是否有效

客户端拿到返回的 token 之后,首先需要先解析token,看下有没过期,然后调用Dex /keys 接口获取公钥,再到本地校验 token 是否有效。

如果有效,还会再解析 id_token,获取其中的一些参数如:username、email等,当然这里还可以自定义一些参数进去。

以下是我这边解码的结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"iss": "https://auth.lusyoe.com",
"sub": "CgExEgluY2FsZW5kYXI",
"aud": "ncalendar",
"exp": 1748852237,
"iat": 1748765837,
"nonce": "cft61j0f96i",
"at_hash": "-De6VpFIe4FFTcj4J1IWGA",
"c_hash": "MQbNbAEULN5BcJReLaSMLA",
"email": "xxxx@example.com",
"email_verified": true,
"groups": [
"admin"
],
"username": "xxx",
"is_admin": false
}

7️⃣ 客户端验证并存储登录态(创建本地 Session/token)

虽然获取了 id_token,但多数 Web 应用会在此基础上创建本地 session,以便后续鉴权、刷新、用户信息维护等操作,当然也可以使用这个公共的 id_token,只是可能不太安全。

我这里是创建的 jwt token,然后写入到浏览器的 cookie 中,后续使用自己的 token 进行鉴权。

8️⃣ 跳转到用户个人信息页面

最后一步就是重定向前端页面跳转到用户个人信息页面,在这个页面也会自动携带 cookie 里面的token,供我们后端验证。

✅ 总结

Dex 作为开源的 OIDC 提供器,能够以标准化、安全、可扩展的方式,为多系统、多客户端实现单点登录(SSO)。

自己也可以很方便的实现 connector,跟自建的系统进行对接,同时也很容易跟第三方系统对接,如:github、google等。

🔚 总之无论你是要将 Dex 集成到自建服务,还是希望接入外部认证平台(如企业微信、钉钉、短信验证码系统),理解以上流程都是实现稳定、安全 SSO 的关键第一步。