KEEL · 龙骨 · A CURRICULUM FOR THE AI ERA

SSO 应用课:从「跳回来一片空白」到能自己排出故障顺序 — keel 龙骨

SSO 工程课:协议、令牌与会话 的参考信息:SSO 应用课:从「跳回来一片空白」到能自己排出故障顺序

7 章 · 每章都用同一套可运行的报文与一套可改的最小实现

接入 SSO 最难的一刻,不是配置写完的时候,而是它不工作时的排查。

回调地址上多了一个 ?code=...,页面一片空白;令牌换不回来,日志里只有一行 invalid_grant;
本地登出干净,另一个系统还登着。这些现象有一个共同点:每一步都是“明明按文档写了”。
看文档看不出问题,因为文档讲的是每一步该做什么,而故障出在步骤之间——
谁记住了什么、什么只能用一次、什么时候必须清掉。

这门课从报文出发:先把一次登录的每一个来回摊开,再把「哪一步之后什么不能再用」
变成可以亲手注入的代码,最后收在生产环境的替换点上。

三个现场

现场一:回调地址上带着 code,应用却什么都没拿到。

开发者把「换 token」这一步写在浏览器里,或者把 code_verifier 存在了 Session Storage。
换到一半失败,重试一次,服务器说 Code not valid——同一个 code 已经用不上了。
code 是一次性的,而且失败的那一次也算用过。这一条不知道,排障就会往完全错误的方向找。

现场二:登录明明成功了,第二个应用还是弹登录页。

单点登录成立的条件不是「登录过」,而是浏览器侧那个 cookie 还在。
把「已登录」记在了应用自己的 session 里,IdP 就会在第二步笑眯眯地再要一次密码——
因为它不认识你。搞清楚「已登录」记在哪一侧,是单点登录能不能成立的分界线。

现场三:更换 IdP 地址之后,所有应用一起报 issuer 不匹配。

issuer 是一个字面量,不是「大致相同的地址」。http 与 https、有没有端口、
末尾有没有斜杠,差一个字符就是另一个 issuer。生产环境前面一旦加了代理,
应用收到的 iss 就可能不是它配置里那个——这类故障从现象上看和「签名不对」一模一样。

这门课回答什么

你可能正在纠结的问题 在哪一章
OAuth 2.0 / OIDC / SAML 到底各管哪一层?我这个场景该选哪个? 01
第一步 GET 为什么给的是登录页而不是 code?回跳那四个参数都是什么? 02
PKCE 的 code_verifier 是给谁用的?为什么填错一次就再也换不回来? 02
ID Token 和 access token 都叫 token,aud 为什么一个是客户端一个是 account? 03
nonce / at_hash / sid / auth_time 各自在防什么? 03
单点登录到底靠什么成立?登出为什么两个系统要一起清? 04
一个应用要接多家 IdP,怎么区分?sub 能当账号用吗? 05
登录失败但看不出哪一步断的,从哪查起? 06
教学里单实例够用,真实部署要在哪些地方换掉? 07

这门课不回答什么

章节地图

01 全景与选型 ──────────────────────────────  先站到高处:三条协议各在哪一层
        │
        ▼
02 授权码流与 PKCE ────────── 03 令牌与校验   把一次登录逐步走通,再拆开三个 token
        │                              │
        ▼                              ▼
04 会话与登出 ────────────────────  单点登录靠什么成立、登出为什么要清两处
        │
        ▼
05 联邦与多租户 ──────────────  一个应用接多个 IdP 时的区分与接缝
        │
        ▼
06 故障注入与排障 ────────────  五类故障的「症状 → 去哪看 → 根因」
        │
        ▼
07 生产边界 ──────────────────  逐条把教学替身换成真实依赖

七章的分工是**「先走通、再拆开、再破坏、最后换掉」**:02 走通一次完整登录,
03 拆开它拿回来的三样东西,04 回答「为什么第二次不用再登录」,05 把视角从一个应用抬到多个系统,
06 把前面所有结论当作已知去制造故障,07 收在生产替换点上。

配套项目

course/project/ 是一个只用标准库的最小 OIDC 实现:一个最小 OP(授权端点 / 令牌端点 / JWKS / 会话 / 登出)
加一个最小 RP,加一个会管 cookie 的「浏览器」。它不替代 Keycloak,只做一件事:
把「协议报文里到底交换了什么」变成可读、可改、可注入故障的代码。

cd courses/identity/sso-engineering/course/project
python examples/01_authorization_code_flow.py   # 一次登录的每一步
python examples/02_tampered_verifier.py         # PKCE 失败,且失败也消耗 code
python -m pytest -q tests                       # 34 passed

六个示例的输出逐字可复现(ID 来自顺序工厂、时间来自可显式推进的时钟),
每一条失败路径都断言具体的 error 串。项目自身的说明见 project/README.md。

学完以后你能做什么

关于证据口径


课程导读(起点自检、章节地图表、主案例、前置要求)见 course/README.md。

进入 keel 阅读