OIDC 还是 SAML:你真正需要的是哪一个
由 AI 从英文原文翻译。 阅读原文
每一个开发 B2B 软件的团队,都会在第一次有正经客户说出"我们需要 SSO"时撞上同一个岔路口。两个缩写,OIDC 和 SAML,都自称是答案,而满网都是对比表格告诉你 SAML 是"企业级"、OIDC 是"现代化",然后把你撂在原地,跟之前一样毫无头绪。这里给你一个真正能帮你交付的版本。
它们是什么
SAML 来自 2005 年,本质是 XML。身份提供方对一份断言签名("这是 alice@bigco.com,这是她所属的群组"),然后把它发送给你的应用,应用校验签名并让她登录。它是为浏览器和员工身份场景而生的,那个年代的"企业"意味着本地部署的 Active Directory 和一套 SOAP 技术栈。它冗长、它老旧,而且在大型组织内部无处不在——这才是关于它你唯一需要在意的事实。
OIDC 来自 2014 年,本质是 JSON 和 JWT,构建在 OAuth 2.0 之上。身份提供方签发一个 ID 令牌,由你的应用来校验。它是为现代 Web 而生的:SPA、移动应用、API、社交登录。它更简洁,对你今天真正在构建的东西有更完善的规范,也是如今大多数全新身份方案所使用的协议。
各自何时胜出
对于"我应该构建哪一个"这个问题,老实的答案是:你几乎从来没有选择权。你构建的是你客户的 IT 部门选定的那一个,而且他们早在听说你之前就已经选好了。
- 一个使用 Okta、Entra ID 或 Google Workspace 的客户通常两种都能用,而 OIDC 是更舒服的那条路。
- 一个用着老版 ADFS、某个遗留的本地部署 IdP,或一份写于 2016 年的采购清单的客户,会扔给你一堆 SAML 元数据和一封日历邀请,讨论到此为止。
- 你自己的第一方应用——你的仪表盘和你的移动客户端——要的是 OIDC,没有例外。你绝不会为了让用户登录进你自己的 React 应用而去搬出 SAML。
于是局面清晰地一分为二:现代场景和第一方场景用 OIDC,"因为企业方这么要求"的场景用 SAML。卖给足够多的企业,你就会被要求两者都支持。不是迟早,而是反反复复。
那些坑——也正是自己动手会变得昂贵的地方
SAML 的问题在于它是一种签名 XML 协议,而签名 XML 是应用密码学中最稳定可靠地危险的东西之一。把 SAML 签名校验做错的方式既多又出名:
- 签名包装(XSW): 攻击者移动已签名的元素,把一份未签名、伪造的断言塞到你的解析器实际读取的位置。如果你把校验签名和读取断言做成两个分开的步骤,那你大概率就有漏洞——而几乎每一个初版实现做的恰恰就是这件事。
- 规范化与注释注入: 2018 年那一类漏洞,
user@company.com<!---->.evil.com在签名校验时按一种方式规范化、在你代码读取的字符串里按另一种方式规范化,于是你乐呵呵地把错误的人认证通过了。真实存在的 CVE,涉及多个主流库。 - 那些更不起眼的: 只签名响应却不签名断言、接受未签名的断言、信任 IdP 提供的颁发者却不做固定校验、把断言的有效期窗口算错。每一个都是自己的一颗地雷,而且每一个都被本该懂行的人发布到了生产环境。
OIDC 明显更理智一些,但也并非没有锋利的边角。你仍然得校验正确的声明(iss、aud、exp、以及 nonce)、使用 PKCE、拒绝早已作古的 implicit 流程,还要在轮换和缓存 JWKS 时不至于拒掉一个由你尚未拉取的密钥所签名的令牌。区别在于,OIDC 的陷阱有文档可查、是 JSON 形态的,并且在大多数库里默认就被正确处理。SAML 的陷阱是 XML 形态的,已经吞掉过资源远比你充裕的安全团队。
真正的答案
"OIDC 还是 SAML"是个错误的问题,因为对一款 B2B 产品来说,正确的答案是"都要"。你的现代客户和你自己的应用想要 OIDC。你的企业客户会在一个你无法掌控的时间表上强制要求 SAML。只为其中一个去构建,第三通销售电话就会把它打破。
你真正需要的,是一种能接住每个客户带来的任意协议的办法,而不必搭起两套技术栈、两套元数据管线,以及两次各自独立、各自把签名校验做错的机会。实现才是成本所在。选择从来都不是难的那部分。
而这正是 Authagonal 替你卸下的那部分。每个租户都能获得带一键元数据导入的 SAML 2.0,以及与你客户已在使用的提供方对接的 OIDC 联合登录,二者共用同一个登录入口,且任何一种都不收取按连接计费的费用。你不必实现 XML 签名校验,不必照看 JWKS 缓存,也不必在下一个说着另一种协议的客户出现时把这一切重建一遍。看看都包含了什么。