身份平台是少数几个”买贵了会心疼,自建又能把团队拖死”的基础设施。它不是一次性采购,而是一个会伴随业务 5 至 10 年、每一次合规审计和每一次安全事件都要被重新审视的长期合同。身份平台的选型一旦落地,后续想换的边际成本极高:密码 hash 要迁、session 要双写、下游几十上百个 SP 要逐个改配置、用户要被反复教育。因此选型阶段投入的调研成本,远比选错之后的补救成本便宜。本文不做厂商软文对比,而是站在做过两次自建、两次替换 SaaS 的工程视角,把 Keycloak、Auth0、Microsoft Entra ID、Okta 以及 Ping、ForgeRock、Authentik、FusionAuth、Zitadel 这一圈选手放到同一张桌子上,按实际成本和实际坑拆开讲。
文章会沿着这条主线展开:先给一个可执行的决策框架(TCO、合规、SLA、生态),然后逐家拆解真实成本与扩展能力,最后落到决策矩阵、工程坑点和迁移成本。Keycloak 的内部实现参见 Keycloak 工程拆解,CIAM 场景的细节参见 CIAM 架构,跨平台搬家的操作手册参见 身份平台迁移。
一、决策框架:不是”贵不贵”,是”总账”
在开始拆解各家之前,先把”自建 vs 采购”这个老问题的讨论层级拉正。太多团队把这件事当成一次性采购,评估维度停留在”license 一年多少钱 + 服务器一年多少钱”,然后在一年后被运维、合规、迁移、安全响应的隐性账单反复追打。身份平台的正确算法是一本 3–5 年维度的总账,而且这本账的成本结构会随着 MAU、合规等级、组织形态的变化而重新改写。
1.1 TCO 要算进去的科目
绝大多数团队在”自建 vs 采购”这一步就算错了账,因为只对比了 license 费和服务器费。一个能真实使用的 TCO 模型至少包含下列科目:
| 科目 | 自建(Keycloak 为例) | SaaS(Auth0/Okta/Entra) |
|---|---|---|
| 软件 license | 0(Apache 2.0) | MAU 或 per-user 计费 |
| 基础设施 | EC2/EKS、RDS、Redis/Infinispan、跨 AZ 带宽 | 0 |
| 工程人力 | 至少 1 FTE 熟悉 Keycloak,通常 1.5–2 FTE | 0.2–0.5 FTE 对接 |
| 安全响应 | 自己跟 CVE、打补丁、回归测试 | 厂商负责,但仍需关注事件通告 |
| 升级成本 | 每年至少 1 次大版本升级,有 breaking | 厂商滚动升级,偶尔 API deprecation |
| on-call | 7x24,SSO 挂了全公司业务停 | 厂商 SLA 兜底 |
| 迁移代价 | 从 0 到 1 较轻,从 1 到另一家较重 | 越用越锁定 |
| 合规与审计 | 自证合规(等保测评、审计报告自备) | 用厂商的合规资质(ISO、SOC2、FedRAMP) |
一条经验法则:当 MAU 低于某个临界点(经验值大约 5–10 万)时,SaaS 的 MAU 费用低于”1 个熟悉 Keycloak 的工程师 + HA 基础设施”的年成本;临界点之上,自建会开始变得便宜,但前提是你真的有那个人。
给一个具体的数字示例,帮助把账算透。假设某 SaaS 产品当前 8 万 MAU,预计两年后到 40 万 MAU。若选择 Auth0 Professional:
当前:8 万 MAU ≈ $1,500/月(含 B2C + 少量 M2M)
1 年后:20 万 MAU,Professional 升到 Enterprise,合同价约 $60k/年
2 年后:40 万 MAU,企业合同约 $120k/年
两年累计 SaaS 支出:约 $200k
若选择 Keycloak 自建:
基础设施:$14k/年 × 2 = $28k
1.5 FTE 平台工程:80 万 × 1.5 × 2 = 240 万人民币,约 $340k
安全/合规审计外包:$20k × 2 = $40k
两年累计:约 $408k
在 40 万 MAU 以内,Auth0 的总成本仍然低于自建。但如果业务在两年后冲到 500 万 MAU:
Auth0 500 万 MAU 级别,企业合同常见 $400k–$800k/年
Keycloak 同规模:基础设施翻到 $40k/年,FTE 2 人保持不变
两年累计:Auth0 约 $1.5M,Keycloak 约 $760k
这就是为什么大厂几乎都走自建:规模化之后 SaaS 的 per-MAU 线性成本会压垮账面。但在 10–50 万 MAU 这个中间带,结论高度依赖团队能力,不要闭眼照搬别人的答案。
1.2 合规要求倒逼选型
合规是选型里最硬的约束,它经常直接排除一半候选。
- 等保三级 / 关基 / 金融行业:需要数据本地化、审计日志留存、国密算法支持。境外 SaaS 基本出局,除非厂商有国内实体与中文审计报告(Okta、Auth0 在国内合规通路目前非常薄弱)。
- GDPR:欧洲数据驻留要求。Auth0 提供 EU tenant,Entra ID 有欧洲数据边界(EU Data Boundary),Okta 有 EU cell。
- FedRAMP:美国联邦政府。Okta 有 FedRAMP Moderate/High,Microsoft 有 Azure Government,Auth0 有 FedRAMP Moderate,但价格与普通商业版差距极大。
- HIPAA/PCI-DSS:主流 SaaS 都能签 BAA,但要确认是哪个 edition 才支持。
- 国产化替代:等保 + 党政军 / 国企场景,国产 IAM 产品(玉符、竹云、派拉、芯盾等)或 Keycloak 自托管是主流路径。
1.3 SLA:自建 HA 到 99.99% 有多难
SaaS 厂商通常给出 99.9%(月度约 43 分钟不可用)到 99.99%(月度约 4 分钟)的 SLA。自建要达到同等级别,需要:
- 多可用区部署,至少 3 个 Keycloak 实例。
- Infinispan cross-site 复制或 external cache,保证 session 不丢。
- 数据库 HA(RDS Multi-AZ 或 PostgreSQL 主从 + 自动切换)。
- 跨区域灾备(DR),这一层通常是被放弃的。
- 全链路可观测:SSO 挂了要在 1 分钟内知道。
- 升级演练:灰度发布 Keycloak 本身需要独立的演练流水线。
坦白说,多数自建团队能稳定做到 99.9%,99.99% 只有专职平台团队能摸到。
1.4 生态与扩展性
身份平台的价值不只在登录,还在它能不能快速接入新的 SaaS 和能不能被你的业务扩展:
- SaaS 目录:Okta 的 OIN 有 7000+ 预集成应用,Entra ID 的 gallery 有 3000+,Auth0 较少,Keycloak 靠 SAML/OIDC 通用协议自己配。
- 扩展方式:Keycloak 有 SPI(Java)、Auth0 有 Actions(Node.js)、Okta 有 Workflows 与 Inline Hooks、Entra 有 External ID Custom Policy 与 API Connectors。
- 目录服务:Entra ID、Okta Universal Directory、Keycloak(借数据库)都可以当主目录;Auth0 的 user store 更像登录态而非完整 HR 目录。
1.5 决策顺序的建议
我见过团队开会花三周讨论”选哪家更便宜”,但忽略了一个更本质的问题:先确定约束,再选平台。推荐的顺序是:
- 合规 / 数据本地化约束列清楚,一票否决。
- 生态绑定列清楚(是否 M365、是否已有 AD、是否大量 SAML 老应用)。
- 团队能力列清楚(是否有 Java / Node 工程师、是否有 SRE 能做 HA)。
- 预算列清楚(年度上限、两年增长预测)。
- 再谈具体产品。
如果前四步中的任一项给出了强信号(比如”必须数据本地化”、“已有 E5 license”),往往 5 的答案就自动出来了。
二、Keycloak 自托管:真实成本拆解
Keycloak 是开源身份平台里最成熟的一支,CNCF 观察名单、Red Hat 背书、巨大的社区。但”开源”不等于”免费”,它只是把账单从厂商转到了你自己团队。下面把这笔账拆到每一项。
2.1 至少需要一个”懂 Keycloak 的人”
Keycloak 的坑不在于启动,而在于生产化。一个真正能扛住线上事故的工程师,至少要熟悉:
- Realm、Client、Flow、SPI 的概念与边界(参见 Keycloak 工程拆解)。
- Infinispan 的 cache 拓扑与 split-brain 行为。
- PostgreSQL 或 MariaDB 的表结构(user、user_entity、credential、user_session 等)。
- 升级时的 DB migration 脚本与回滚策略。
- 能读 Java 代码、能写 Authenticator SPI。
按 2024 年国内一线城市高级工程师的综合成本(薪酬 + 社保公积金 + 股票 + 分摊的管理成本),一个人年成本约 80–150 万人民币,海外更高。这是自建故事的第一张账单。
2.2 安全响应的现实时间线
举 2023–2024 年几个 Keycloak CVE 的例子可以看到响应成本:
- CVE-2023-6927:Keycloak redirect_uri 校验绕过,影响 22.0.5 之前版本。
- CVE-2023-6134:XSS via reset credentials。
- CVE-2024-1722:通过 SAML 响应触发的认证绕过(需特定配置)。
自建团队的真实流程是:安全邮件列表订阅 → CVE 评估 → 打补丁或升级次版本 → 在 staging 回归(登录、MFA、社交登录、SPI) → 灰度发布 → 观察一周。从 CVE 公开到生产修复,经验数据是 1–4 周,这期间你在跟时间赛跑。
2.3 HA 部署的资源账
一个能承载 10 万–50 万 MAU、99.9% SLA 的 Keycloak 集群最小配置大致是:
Keycloak: 3 × (4 vCPU / 8 GB) 约 $400/月
PostgreSQL HA: RDS db.m6g.large Multi-AZ 约 $300/月
Redis/Infinispan external: 2 × cache.m6g.large 约 $200/月
LB + WAF + 带宽: 约 $150/月
日志与监控(Prometheus、Loki、Grafana) 约 $100/月
合计 约 $1,150/月 ≈ $14k/年
这只是基础设施,不包括跨区域灾备、审计日志合规存储、以及工程师工资。
配置上还有几个常被忽略的点:
- JVM 调优:Keycloak 22+ 基于
Quarkus,启动快但堆外内存不小,默认
-Xmx设 4G 经常 OOM,需要配合MALLOC_ARENA_MAX=2控制 glibc 的 arena 数。 - 连接池:数据库连接池默认偏小(Quarkus 默认
20),用户量一大会成为瓶颈,需要调整
quarkus.datasource.jdbc.max-size。 - 登录风暴:某个 SSO
客户端下游故障重试会打出登录尖峰,Keycloak 的 Brute Force
Detection 会误杀,需要按 realm 调
failureFactor与waitIncrementSeconds。 - 会话大小:一个活跃 user_session 内存占用约 5–15 KB,100 万 session 大约 10 GB,Infinispan 堆需要预留。
2.4 Infinispan cross-DC 的复杂度
Keycloak 跨数据中心部署时,Infinispan 的 cross-site replication 是大多数团队的噩梦。实际遇到过的问题:
- Sync 模式下跨区域延迟会把登录 RT 拉到秒级;async 模式下 session 不一致会让 refresh token 偶发失败。
- Site takeover 后需要手动协调 cache,否则新 site 会收到脏数据。
- Keycloak 26 开始官方推荐 external Infinispan cluster + multi-site active-passive,旧版本的 embedded + active-active 实际上已经不推荐。
2.5 升级风险:大版本的 breaking changes
Keycloak 的发布节奏很快(每月一个次版本,每年若干次带 breaking 的大版本)。踩过的坑:
- 17.0 从 WildFly 切到 Quarkus:配置文件、启动参数、主题路径全变。
- 19–21 期间 refresh token rotation 的默认策略变更。
- 24–25 对 account console、admin console 的 REST API 做了整改。
- 26 弃用 embedded Infinispan cluster 模式。
跳版升级(比如 15 → 23)几乎等于重装,DB migration 脚本有时要执行数十分钟并锁表,生产环境必须停机或分批迁移。
推荐的升级节奏:
- 跟 LTS(Red Hat SSO / Red Hat build of Keycloak)或每年至少跟两次社区版,避免跨度过大。
- 维护一条自动化 pipeline:pull 新版本镜像 → 在 staging 跑冒烟 → 在灰度集群暴露 5% 流量一周 → 全量切换。
- 把主题、SPI、Provider 统一打包进自定义镜像,不要依赖运行时挂载 jar,避免升级时遗漏。
- 对主题的修改尽量使用
parent继承原生主题,少覆盖整份模板,减少新版本 UI 改动带来的冲突。
2.6 自建的组织成本
除了技术成本,还要算”组织成本”:
- on-call 排班:身份平台故障 = 全公司登录不了,必须 7x24,至少 3 人轮班。
- 知识传承:Keycloak 里深度定制的 SPI、Flow、Provider 依赖个人经验,一旦人员流失,接手周期通常 2–3 个月。
- 内部支持:业务线会不停提接入、改主题、加 claim 的需求,平台团队很容易被消耗在工单上,需要治理工具(Terraform provider、GitOps)。
- 安全资质:自建意味着自证合规,审计师会直接看你的运维记录、变更记录、漏洞响应记录,准备成本不低。
这些组织成本在 SaaS 方案里被厂商吃掉,换成了账单;在自建里,如果没有专门的平台工程文化,会慢慢显化为工程师的加班与离职。
2.7 适合场景
- 技术团队强,有专职平台工程岗。
- 有合规或数据本地化硬性要求。
- 定制需求深(自定义 Flow、自定义凭证、自定义账户页面)。
- 对单位用户成本敏感、规模大。
三、Auth0(Okta 旗下)
Auth0 是”开发者友好 CIAM”的代表,2021 年被 Okta 收购后合入 Customer Identity Cloud 产品线,但品牌与控制台仍独立。选择 Auth0 最大的理由是它能让一个 3 人团队在一周内跑通”注册、登录、社交、MFA、B2B 多租户”的完整 CIAM 流程,代价是 per-MAU 成本与供应商锁定。
3.1 定价模型
Auth0 按 MAU(Monthly Active User,30 天内至少登录一次的用户)计费,2023–2024 年公开价目大致如下(以 USD、美国区为准,实际以官网为准):
- Free:最多 7,500 MAU,社区支持,无 SLA。
- Essentials:从约 $35/月起(500 MAU),按 MAU 阶梯上浮。
- Professional:从约 $240/月起(1,000 MAU),支持 RBAC、MFA、Organizations。
- Enterprise:年合同起,自定义价格,通常从 $30k/年起步。
Auth0 的定价分 B2C 和 B2B(Organizations)两条线:B2B 版本的 per-org 费用更高,但换来天然的多租户隔离。一个常被忽略的点是 M2M token 单独计费:机器到机器的 client credentials 交易,每月免费额度用完后按次计费。
容易踩的定价陷阱:
- MAU 的定义是”30 天窗口内至少一次成功登录”,不是注册用户数。风控误判导致用户反复登录,会把 MAU 推高。
- B2C 与 B2B 不能混用一个 tenant 计费:同一套用户想要两种定价优势,只能拆 tenant 或走 Enterprise 谈判。
- MFA 额度:Essentials 只有基础 MFA;Guardian(Push)与 SMS 在 Pro 起才能用,SMS 本身还按条付费。
- 非活跃用户的静态存储是免费的,所以长尾数据不要急着清理,反正不计费。
- Extensions 与自定义域名(Custom Domain)在 Essentials 以下不可用,B2C 上线前容易踩。
3.2 扩展能力
- Actions:Node.js serverless,可在登录、注册、post-login 等 trigger 点执行代码。支持 npm 依赖(有白名单),冷启动通常在 100–300ms。
- Organizations:B2B 专用,一个 tenant 下多个 Organization,每个 Organization 可绑定独立连接(企业 SSO)。
- Database Connections、Passwordless、Social、Enterprise Connections(SAML、OIDC、AD/LDAP)都是开箱即用。
- Machine-to-Machine:client credentials flow,可签发 audience 隔离的 access token。
一个 Action 示例,展示”在登录时从内部 CRM 拉取企业账户信息并写入 token”:
exports.onExecutePostLogin = async (event, api) => {
const axios = require('axios');
const tenantId = event.organization?.id;
if (!tenantId) return;
try {
const resp = await axios.get(
`https://crm.internal/api/orgs/${tenantId}`,
{ headers: { Authorization: `Bearer ${event.secrets.CRM_TOKEN}` }, timeout: 2000 }
);
api.idToken.setCustomClaim('https://example.com/plan', resp.data.plan);
api.accessToken.setCustomClaim('https://example.com/plan', resp.data.plan);
} catch (err) {
console.log('crm lookup failed', err.message);
}
};这种模式干净利落,上线速度比 Keycloak SPI 快一个数量级。代价是:依赖 CRM 的网络抖动会直接影响登录,生产上必须加短超时 + fallback,不然一次下游抖动会登录不了。
3.3 Vendor lock-in:Actions/Rules 不可移植
Auth0 的最大锁定点在 Actions。Actions 用的是 Auth0 定义的 event object 与 api 对象:
exports.onExecutePostLogin = async (event, api) => {
if (event.user.email_verified === false) {
api.access.deny('Email not verified');
}
api.idToken.setCustomClaim('https://example.com/roles', event.user.app_metadata.roles);
};这段代码搬到 Keycloak,要改写成 Authenticator SPI + ProtocolMapper;搬到 Okta,要改写成 Inline Hook。越是把业务逻辑写进 Action,迁移越贵。经验数据:一个中等复杂度的 Auth0 tenant(30+ Rules/Actions、5+ 自定义数据库连接脚本、若干自定义页面)迁移到 Keycloak,需要 3–6 人月。
除了代码不可移植,还有几类隐性锁定:
- 自定义 Database Connection 里的
login、create、verify、change_password、get_user五段脚本,逻辑耦合在 Auth0 runtime 里。 - Universal Login 的 Page Templates 用 Liquid 模板 + Auth0 JS SDK,迁移必须重写前端。
- Hooks 与 Extensibility 中的 secrets、rule configurations 是 Auth0 独有的 KMS 托管,迁移要重新规划密钥存放。
- Auth0 的 user_id
格式(
auth0|xxx、google-oauth2|xxx)经常被业务侧持久化到自家 DB,迁移后需要做 ID 映射层。
3.4 适合场景
- 初创公司、B2C 产品,需要 1 周内上线完整身份体系。
- 产品团队里没有 Java 工程师,但 Node.js 熟。
- 规模在 10 万 MAU 以内,对单位用户成本不敏感。
四、Microsoft Entra ID(前 Azure AD)
Entra 是 Microsoft 2023 年对身份产品线的整体重命名:Azure AD → Entra ID,Azure AD B2C → Entra External ID,再加 Entra Verified ID、Entra Permissions Management 等。在企业身份市场里,它和 Okta 是两极,分别代表”Microsoft 生态一体化”与”中立独立厂商”两种选型哲学。
4.1 Microsoft 生态绑定
Entra ID 的杀手锏不是身份本身,而是 Microsoft 生态的一体化:
- M365 集成:买了 E3/E5 license,Entra ID P1/P2 通常打包其中。
- 条件访问(Conditional Access):基于用户、设备、位置、风险的访问策略,是企业 IT 的标配。
- Intune 设备合规:MDM + MAM,登录时校验设备是否合规。
- Defender for Identity、Purview:威胁检测、数据合规。
对已经深度使用 M365 的企业,Entra ID 基本是默认选项,因为边际成本极低,而 SSO 到 Office/Teams/SharePoint 是原生的。
条件访问是 Entra 相比其他平台一个特别有竞争力的能力。一个典型策略:
Users: All users excluding "Break glass accounts"
Cloud apps: All cloud apps
Conditions:
- Sign-in risk: High, Medium
- Device platforms: Windows, macOS, iOS, Android
- Locations: Exclude trusted IPs
Grant:
- Require MFA
- Require device to be compliant (Intune)
- Require approved client app
Session:
- Sign-in frequency: 4 hours
- Persistent browser session: Never
这类策略组合在 Okta 也能做(Adaptive MFA + Device Trust),但 Entra 的特色是与 Intune、Defender 的信号打通:Defender 检测到终端异常,条件访问可以立即把该设备标红并阻断。
4.2 Entra External ID(前 Azure AD B2C)
Entra External ID 是微软的 CIAM 产品。2023 年做了品牌整合:原 Azure AD B2C 继续维护,但新项目推荐迁到 External ID。
定价模型:
- MAU-based:前 50,000 MAU 通常免费,之后按 MAU 阶梯收费。
- 交互次数:MFA、SMS、电话验证按次另收。
工程上最大的痛点是 Custom Policy。Custom Policy 用 XML 定义整个认证旅程(Trust Framework),灵活但学习曲线极陡:
<OrchestrationStep Order="1" Type="ClaimsExchange">
<ClaimsExchanges>
<ClaimsExchange Id="LocalAccountSigninEmailExchange"
TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" />
</ClaimsExchanges>
</OrchestrationStep>一个真实样本:实现一个”邮箱注册 + 短信二次验证 + 同步到内部 CRM”的旅程,Custom Policy XML 文件通常要 1000–3000 行,调试只能靠 Application Insights 里的 traces,错误信息相当晦涩。
Custom Policy 的结构分成三层:
- TrustFrameworkBase.xml:微软提供的基线,不要改。
- TrustFrameworkExtensions.xml:公司级扩展,定义 ClaimType、TechnicalProfile、ClaimsTransformation。
- SignUpOrSignin.xml / ProfileEdit.xml 等:具体用户旅程(RelyingParty)。
一次修改经常要同时动 Extensions 和 RelyingParty 两个文件,而且必须按顺序上传(Base → Extensions → RelyingParty),上传错顺序会出现 “PolicyId not found”。
如果你不需要定制到骨子里,优先使用 User Flow(旧名 Built-in Policy),那是基于界面的配置。只有在 User Flow 无法满足(比如需要调用外部 API 丰富 claim、需要条件分支、需要自定义 UI strings 的多语言)时才动 Custom Policy。
4.3 适合场景
- 已经使用 M365 E3/E5 的企业,尤其是有条件访问、Intune 需求的。
- 需要原生集成 Windows Hello、FIDO2、Passwordless 的场景。
- 非纯 B2C 场景,或 B2C 团队能吃下 Custom Policy 学习成本。
五、Okta
Okta 是独立身份厂商里规模最大的,2009 年成立,2017 年 IPO。它的定位是”中立的企业身份平台”,不绑定任何云厂商,因此在多云、非微软生态、大型非技术驱动型企业里是默认选项。收购 Auth0 后产品面扩展到 CIAM,但两条产品线仍然在逐步整合。
5.1 产品线
Okta 收购 Auth0 之后,产品线清晰为两条:
- Workforce Identity Cloud(WIC):企业内部员工身份,SSO、MFA、Lifecycle Management、Access Governance。
- Customer Identity Cloud(CIC):即原 Auth0,用于 B2C/B2B 面向客户的身份。
WIC 的核心能力:
- Universal Directory:企业主目录,可与 AD、LDAP、HR 系统双向同步。
- Okta Workflows:no-code 流程自动化,类似 Zapier,用来做 JML(Joiner/Mover/Leaver)。
- Lifecycle Management:自动给新员工开通 SaaS 账号、离职自动收回。
- Adaptive MFA、Device Trust、ThreatInsight。
Workflows 的一个典型场景:Workday 创建新员工 → Okta 自动触发 Workflow → 在 AD 里建账号 → 分配到部门 OU → 在 Box、Slack、GitHub、Salesforce 开账号 → 分配对应 group → 发送 welcome 邮件与临时密码。整套流程在 Workflows 的可视化编辑器里配置,无需代码。反过来,离职触发 Workday 事件 → 自动禁用 → 撤回全部 SaaS 访问 → 归档数据 → 7 天后彻底删除。对大型企业,这种 JML 自动化能省掉一整支 IT 运维小组。
5.2 价格
Okta 的定价偏高且不透明。典型年合同:
- Workforce SSO:$2/user/月起。
- Adaptive MFA:$3/user/月起。
- Lifecycle Management:$4/user/月起。
- API Access Management:$2/user/月起。
- 大企业打包后常见是 $4–$8/user/月,Enterprise Identity Bundle 更高。
对于 1 万员工的公司,Okta 的年支出容易到 $500k 级别。
5.3 2023 年安全事件的教训
2022 年 Lapsus$ 通过 Okta 的客户支持供应商 Sitel 获得了一个工程师工作站的访问权限,虽然 Okta 官方说法是影响面有限(约 2.5% 客户),但引发了企业对”身份平台本身是不是单点”的深度担忧。2023 年 Okta Support Case Management System 又被入侵,攻击者获取了包含 session token 的 HAR 文件,影响 1Password、BeyondTrust、Cloudflare 等多家客户。
教训:
- 把身份平台本身也纳入威胁建模,特别是 support portal 上传的 HAR 文件必须先脱敏。
- 管理端开启强制 phishing-resistant MFA(FIDO2/硬件 key)。
- 定期轮换 admin session,异常 session 要能被强制回收。
这两起事件还有一些更深层的架构启示:
- 不要把所有鸡蛋放在一个 IdP 篮子里。生产系统的 break-glass admin 账户应该独立于主 IdP,放在硬件 key + 离线保险箱里,避免主 IdP 失陷时无法救援。
- 关键 downstream(比如云平台 root、代码仓库 org owner)应该有独立的 MFA,不仅仅依赖 SSO。Cloudflare 在 2023 事件中能及时止损,就是因为对 Okta 签发的 session 做了二次校验。
- 第三方供应商(客服、外包运维)的访问路径必须是最小权限、时间受限、全量审计,并且假设他们会被攻破。
- 审计日志要导出到 IdP 之外的存储,否则攻击者拿到 IdP admin 权限可以篡改日志。
5.4 适合场景
- 大型企业、尤其是非 Microsoft 生态的。
- 有大量 SaaS(Salesforce、Workday、ServiceNow、Slack 等)需要统一 SSO 和 Lifecycle 的。
- 有合规和审计要求,希望把身份作为治理平台。
六、其他值得关注的选手
四大选手之外,还有一批在特定场景下值得评估的产品。下面这些不是”次等选项”,而是在合适的场景下反而是最优解。
6.1 Ping Identity
传统企业市场老牌选手。PingFederate 在 SAML、WS-Federation、旧协议对接上非常强,是很多银行、保险、运营商的默认选择。2022 年被 Thoma Bravo 私有化,2023 年合并 ForgeRock,目前产品线整合中。适合已有大量遗留应用(比如 IBM DataPower、旧 WebSphere 集群)的企业。
Ping 的几个独到之处:
- PingAccess:反向代理模式下的 web access management,可以在不改造老应用的情况下加 SSO,是迁移旧 Siteminder 的最佳路径。
- PingDirectory:基于 LDAP 的高性能目录,单实例可扛 10 亿条目,是运营商级客户的主要选型理由。
- PingOne Cloud:近几年主推的云产品,补齐 SaaS 短板。
缺点是传统部署复杂、许可模式不透明、云产品的成熟度仍在追赶 Okta / Entra。
6.2 ForgeRock
被 Ping Identity 收购后,产品(AM、IDM、DS)正在与 Ping 的线融合。ForgeRock 的强项是 CIAM 和身份治理(IGA),在北欧、电信运营商市场有一批老客户。新项目一般不再独立选 ForgeRock。
6.3 Authentik
开源、Python/Go 实现,界面现代,扩展通过 policy engine(Python 表达式)。适合中小团队希望开源但又觉得 Keycloak 太重的场景。生态小,企业合规支持弱。
6.4 FusionAuth
开发者友好的 SaaS / self-hosted 双模式,MAU 定价相对透明。扩展能力较完整(lambdas、webhooks),社区版可免费自托管,定价可预测性好。适合不想吃 Keycloak 运维但也不想被 Auth0 锁定的团队。
6.5 Zitadel
Go 实现、event-sourcing 架构、cloud-native。多租户设计干净,gRPC + OIDC 原生。国内使用者还不多,但在 Kubernetes 原生、微服务场景下是值得跟踪的新选手。
Zitadel 的技术亮点:
- event sourcing + CQRS,所有写入是 append-only 事件,审计天然完整。
- 原生多租户(Organization),适合 B2B SaaS。
- Actions 用 JavaScript / Go,可运行在 v8 沙箱。
- 部署形态干净:一个二进制 + PostgreSQL,Helm chart 成熟。
短板是生态小、SAML 支持比 Keycloak 粗糙、中文社区几乎为零,企业合规支持只有 SOC2 起步。适合技术驱动的 SaaS 团队,不适合合规审查重的大企业。
6.6 国产 IAM 选手
在境内等保 / 党政军 / 金融私有化场景,通常还会遇到下列选手:
- 玉符科技 IDaaS:CIAM + IGA 能力较完整,合规资质齐全。
- 竹云科技:偏传统 IAM / IGA,政企客户多。
- 派拉软件:运营商、银行市场占有率高。
- 芯盾时代:强项在设备指纹、风控。
- 九州云腾、宁盾等:各有细分场景。
选型时重点评估:是否有等保三级测评报告、是否支持国密 SM2/SM3/SM4、是否支持国产操作系统(麒麟、统信 UOS)与国产数据库(达梦、OceanBase、TDSQL)、是否有行业标杆案例。境外产品在这些维度上几乎全军覆没。
七、决策矩阵
下面这张矩阵是结合项目经验整理的”不同场景首选 + 次选”,仅供起点:
| 场景 | 首选 | 次选 | 说明 |
|---|---|---|---|
| 初创,MAU < 5 万,3 人工程团队 | Auth0 / FusionAuth | Zitadel Cloud | 先跑起来,别在身份上浪费 6 个月 |
| 成长期,5 万–50 万 MAU,有平台工程 | Keycloak / Zitadel / Auth0 Pro | FusionAuth | 临界点,按 TCO 再算一次 |
| 大企业,Microsoft 生态 | Entra ID | Okta | 有 M365 就别自讨苦吃 |
| 大企业,非 Microsoft 生态 | Okta | Ping / Entra ID | 看 SaaS 目录与 Lifecycle 需求 |
| 等保三级 / 金融 / 数据本地化 | Keycloak 自托管 | 国产 IAM(玉符、派拉、竹云等) | 境外 SaaS 基本排除 |
| FedRAMP | Okta FedRAMP / Azure Government | Auth0 Gov | 价格不要按商业版预估 |
| B2C,重社交登录与风控 | Auth0 / Okta CIC | Entra External ID | CIAM 细节见 CIAM 架构 |
| B2B SaaS,重多租户与企业 SSO 接入 | Auth0 Organizations / WorkOS | Keycloak(一 realm 一 tenant) | 接入客户 IdP 的自动化是关键 |
几个组合场景的判断经验:
- “B2B SaaS 面向欧洲大客户”:客户侧经常要求 SAML + SCIM + 数据在欧洲。如果自建 Keycloak,要准备好欧洲 region 的集群;如果走 Auth0,要用 EU tenant,并确认 Enterprise Connections 的配置工作量(每接一个大客户 IdP 大约 0.5–1 人周)。
- “中国出海东南亚”:Auth0 / Okta 的新加坡 region 是常见选择;数据回流到国内的合规通路要提前确认。
- “混合云 + 私有部署客户”:纯 SaaS 覆盖不了,通常是 Keycloak 自建 + 客户侧 IdP Federation,这时候 Keycloak 的 Identity Broker 能力是关键。
- “传统大企业数字化”:往往不是单选,而是 Entra ID(员工)+ Okta / 国产 CIAM(客户)+ 遗留 PingFederate 的三层并存,迁移按优先级分阶段走。
八、工程坑点清单(必读)
下面这些坑每一条都是生产事故换来的,按平台分组列出。
8.1 Auth0 Rules 到 Actions 的迁移
Auth0 在 2023 年宣布 Rules 和 Hooks 进入 deprecation,End of Life 时间被多次延期(当前公开信息是 2024 年 11 月起停止新建,2026 年底左右完全下线,以官方通告为准)。迁移注意:
- Rules 的执行顺序是数组,Actions 是 trigger 下的 flow,需要重新设计顺序。
- Rules 里的
context、user在 Actions 里被拆成event和api两个对象,字段名不完全对齐。 - Rules 共享的全局函数(configuration、global 对象)在 Actions 里变成 secrets 或 dependencies,必须逐条翻译。
- 同一时间不能混用:一旦开启 Actions,Rules 对同一 trigger 会被跳过。
8.2 Okta LDAP Interface 不是完整 LDAP Server
Okta 提供 LDAP Interface,用来让只会 LDAP 的旧应用(比如 Apache、某些 VPN)接入 Okta。但这不是完整 LDAP:
- 只读,不支持写操作。
- 不支持所有 LDAP filter,复杂的
(&(objectClass=user)(memberOf=cn=xxx))有坑。 - 不支持 referral。
- 通过 STARTTLS / LDAPS,证书是 Okta 签发的。
遗留系统如果依赖 LDAP 写入或复杂搜索,需要加一层 OpenLDAP 作为代理,或者改走 SCIM。
8.3 Entra External ID Custom Policy 调试地狱
Custom Policy 的 XML:
- 没有本地调试器,改完一版要上传,用 App Insights 的 trace 反查。
- 错误信息经常是
AADB2C90xxx一串号码,文档覆盖不全。 - Starter Pack 有四套(LocalAccounts、SocialAccounts、SocialAndLocalAccounts、SocialAndLocalAccountsWithMfa),每套互不兼容,切换成本高。
- TechnicalProfile 嵌套层数深,一个改动可能牵动五个文件。
经验:不要从零写,从 Starter Pack fork,小步修改、每次只改一个 TechnicalProfile,App Insights 采样率开到 100%。
8.4 Keycloak 升级时 DB migration 锁表
Keycloak 启动时用 Liquibase 跑 DB migration。跨大版本升级时:
- 有些 migration 会
ALTER TABLE几十万到千万级的 user_entity 或 credential 表,MySQL 下会全表锁,PostgreSQL 稍好但也会有长事务。 - 建议升级前
pg_dump或 snapshot,在 staging 先用生产规模数据演练。 - 大版本跨度大(比如 15 → 23)时,考虑逐版本升级,每版升完跑冒烟测试。
一个实战片段:18 → 22
升级过程中,offline_user_session 表的 migration
在 500 万用户量下跑了 27 分钟,期间所有 Keycloak
实例启动失败进入重启循环。事后的教训是:
- 在正式升级前,用
--spi-connections-liquibase-default-sync的 dry-run 输出 SQL,手动在维护窗口内先执行大事务,再让 Keycloak 启动时只做小补丁。 - 关键表(user_entity、credential、user_session、offline_user_session、user_federated_identity)升级前先
VACUUM ANALYZE。 - 启动 readiness probe 的超时时间调大到 10 分钟以上,避免 Kubernetes 杀掉正在跑 migration 的 pod。
8.5 SaaS 方案都有 rate limit
所有 SaaS 都有 API 限流,生产化时一定要压测:
- Auth0 Management API:Free/Dev 2 req/s,Enterprise 大约 50 req/s(以官方最新文档为准),批量创建用户、批量导入时很容易打满。
- Okta API:默认 per-org 限流,按 endpoint 分桶,比如
/api/v1/users大约 600 req/min。HTTP 429 会返回X-Rate-Limit-Reset,SDK 需要处理。 - Entra Microsoft Graph:per-app + per-tenant
双重限流,批量操作建议用
$batch。
Auth0 Actions 内部对外部 API 的调用有超时(默认 10s),复杂 Action 里别串行发好几个外部请求。
8.6 其他常见坑
- Refresh token rotation:所有平台默认策略都在变严,一次网络抖动可能让所有 SPA 用户登出,务必在客户端做 dedupe 和重试。
- 时钟漂移:JWT
exp/nbf校验对时钟敏感,所有节点必须 NTP 同步,leeway 设到 30–60s。 - CORS 与 cookie SameSite:SPA + 前后端分离场景下,浏览器对 third-party cookie 的收紧(Chrome Privacy Sandbox)会影响 silent auth,提前切到 refresh token 或 BFF 模式。
8.7 JWK 轮换与下游缓存
所有平台都会定期轮换签名密钥(JWKs),但资源方(API Gateway、业务服务)的 JWK 缓存策略经常有问题:
- 典型 bug:Gateway 启动时拉一次 JWKs,之后永不刷新,厂商轮换后 24 小时全线 401。
- 正确做法:遇到未知
kid时强制刷新一次(带节流,比如最短 60s 一次),并订阅厂商的 key rotation webhook(Okta、Auth0 都有)。 - Keycloak 自托管场景下,realm keys 轮换要走 “enabled → passive → disabled” 三阶段,至少保留旧 key 一个 token 生命周期。
8.8 多 realm / 多 tenant 的管理面
- Keycloak:每个 realm 内部独立,但 master realm 的 admin 权限粒度偏粗;超过 200 个 realm 时,管理控制台性能会明显下降,建议按业务线拆集群。
- Auth0:一个 tenant 无法拆成多 tenant 免费共享配置,dev/staging/prod 各自独立付费,容易被忽视。
- Okta:一个 org 就是一份账单,不同 org 之间同步配置要靠 Terraform 或 Okta Config Management。
- Entra:一个 tenant 原则上承载一整个组织,不建议用多 tenant 做环境隔离,用 AppRegistration + 环境后缀 + 条件访问来隔离。
8.9 审计日志与 SIEM 对接
合规场景下审计日志必须能送到 SIEM(Splunk、Elastic、Sentinel 等):
- Auth0:Log Streams 支持 HTTP、Splunk、Datadog 等,但留存只有 30 天,需要自己长期归档。
- Okta:System Log API,留存 90 天,长期审计需要导出到自己的存储。
- Entra:Diagnostic settings 可导出到 Log Analytics、Event Hub、Storage,留存可配置。
- Keycloak:需要自己配 Event Listener SPI,写到 Kafka 或日志系统。默认的 JBoss Logger 不适合审计场景。
九、迁移成本评估
选错了平台的代价不只是上线那一版,还在于之后想换时有多痛。大多数身份平台迁移项目的真实时长是 6–18 个月,远比管理层预期的长。原因是身份不是一块业务数据,它是所有业务数据的入口,动它等于动所有上游。
从一家到另一家的迁移,密码 hash、session、权限映射、审计合规是四大件,细节放在独立文章 身份平台迁移,这里只列量级:
- 同协议迁移(OIDC → OIDC,比如 Auth0 → Keycloak):中等复杂度 tenant,3–6 人月。
- 跨协议迁移(旧 SAML IdP → OIDC):6–12 人月,业务侧要改大量 SP 配置。
- 密码 hash 迁移:bcrypt / scrypt 通常可直接导入;自研 hash 需要做 lazy migration(首次登录重新 hash)。
- 用户教育:强制重置 MFA 是最大的客户侧负担,一定要分批、预热、提供自助迁移。
一条原则:迁移不是一次性动作,而是双写期 + 灰度 + 回滚方案。从立项到结束通常是 6–18 个月的项目。
迁移前必做的尽调清单:
- 盘点依赖方:有多少 SP(SAML)、多少 OIDC client、多少 M2M 应用,它们分别由哪些团队拥有,SLA 要求是什么。
- 盘点自定义逻辑:Rules / Actions / Hooks / Workflows / Custom Policy 总共多少段,每段逻辑的业务含义是什么,能否等价替换。
- 盘点 identifier:业务 DB 里用 Auth0 user_id / Okta sub / Entra objectId 作为外键的表有哪些,迁移后需要怎样的映射层。
- 盘点审计与合规:原平台的审计日志留存多久、合规报告是哪一版,目标平台能否覆盖同等要求。
- 盘点成本:Enterprise 合同通常有锁定期,提前解约违约金可能比一年的 SaaS 费用更高。
双写期的典型架构:在前端 / BFF 层增加路由开关,新用户走新平台注册,老用户登录时先查新平台、查不到再 fallback 到旧平台并静默迁移。这个阶段通常持续 3–6 个月,期间两个平台都要付费,预算要预留。
十、选型建议
看到这里,读者大概已经感觉不到”哪一家最好”的清晰答案——本来就没有。身份平台选型本质上是一道带约束的最优化题,约束不同解也不同。下面给出可直接落地的三条建议,覆盖绝大多数团队:
最后给出可直接落地的三条建议:
- 别迷信”自建更省”。在 MAU 5 万量级以下,SaaS 的综合成本通常更低。真正能把 Keycloak 运维好的工程师稀缺且昂贵,人力成本远大于 license。
- 合规是一票否决项。先把合规需求列清楚(数据驻留、审计、密码算法),再去圈候选名单。绕过合规选型,后面会花十倍代价补。
- 把可迁移性当一级约束。每一次引入 Auth0 Action、Okta Workflow、Entra Custom Policy,都是在加深锁定。关键业务逻辑(登录、权限判定、token claim 生成)尽量放在自己的服务里通过 hook / webhook 调用,而不是完全写进厂商 DSL 里。这一条是身份平台架构里最容易被低估、也最值钱的设计原则。
再给一张给不同角色的速查建议:
- 创始人 / CTO:头 6 个月用 SaaS,把身份当”肌肉记忆”跑通;留好抽象层,两年后再重新评估自建。
- 架构师:定义内部的 “IdP 抽象”(OIDC 协议层 + 你自己的 claim 规范 + webhook 约定),让业务只依赖这一层,不直接调用厂商 SDK 的专有 API。
- 平台工程 / SRE:如果走自建,第一周就把”升级演练”和”灰度切流”做成自动化流水线,别等到第一次 CVE 来临时才临阵磨枪。
- 安全团队:把身份平台本身纳入威胁模型,强制 admin FIDO2、审计日志入 SIEM、异常 session 能一键回收。
- 合规 / 法务:把”数据驻留地”、“日志留存年限”、“退出数据导出格式”写进合同,这三项通常是后期争议最多的条款。
十一、实施清单与可观测性
无论最终选哪条路,“上线即完事”的项目从来不存在。身份平台的真正工作量在上线之后:每一次新 SaaS 接入、每一次协议升级、每一次安全事件、每一次合规审计,都会重新考验它的运维基线。下面这份清单是项目立项时就应该纳入评估的工程配套。
不管最后选哪家,落地时下面这些工程项都要进计划,不要拖到上线后补。
11.1 可观测性基线
关键指标(RED + 身份专用):
- 登录成功率(按 realm / tenant / connection 分组),低于 98% 就要报警。
- 登录 p95 / p99 延时,重点是到 IdP + 到下游 API 的总链路。
- Token 签发 / 刷新 QPS,识别异常流量。
- MFA 挑战成功率与放弃率。
- JWK endpoint QPS 与缓存命中率。
- 异常事件:brute force 锁定、高风险登录、新地理位置。
工具选择:
- Keycloak:内置
/metrics(Micrometer,Quarkus 版本),Prometheus 直接拉;Event Listener SPI 送审计到 Kafka。 - Auth0:Log Streams → Datadog / Splunk;Insights 仪表盘覆盖基本指标。
- Okta:System Log → SIEM;Syslog streaming 或 Workflows 订阅事件。
- Entra:Azure Monitor Diagnostic Settings → Log Analytics,Sentinel 可做 UEBA。
11.2 容量规划速查
| 规模 | 登录 QPS 峰值 | JWK 校验 QPS 峰值 | 典型瓶颈 |
|---|---|---|---|
| 1 万 DAU | 5 | 500 | 无 |
| 10 万 DAU | 50 | 5,000 | DB 连接池 |
| 100 万 DAU | 500 | 50,000 | JWK endpoint 缓存、下游 API |
| 1000 万 DAU | 5,000+ | 500,000+ | 集群分片、跨区域复制 |
一个经验公式:每个 DAU 每天平均 5–10 次 token 校验(假设 access token 15 分钟 TTL、活跃时段 2 小时)。校验量会远大于登录量,资源方的 JWK 缓存策略决定了系统能不能扛。
11.3 灾备与 break-glass
- 至少准备 2 个 break-glass 管理员账户,凭据离线保管、不走 SSO、强制 FIDO2。
- 定期演练”IdP 全面不可用”的预案:关键系统是否有本地 fallback、API 是否能接受缓存 token 继续服务一段时间。
- 对 Keycloak 自建,准备好跨区域只读副本,可以在主集群故障时降级为只读登录(拒绝新注册,但允许已有用户登录)。
- 对 SaaS,确认合同里的 RTO / RPO 承诺,并验证 exit plan:有没有能力把全量用户与 hash 导出到另一家。
11.4 权限与治理
- RBAC 与 ABAC 的边界:粗粒度角色放 IdP,细粒度(按资源、按属性)放业务服务,别把所有权限都写进 token claim,token 会越来越大。
- Access Review:每季度强制复核高权限账户,工具上 Okta IGA / Entra ID Governance / SailPoint 都可以做,自建场景用 Keycloak + 自研工作流。
- Service Account / M2M:单独 realm 或单独 tenant,避免与用户混在一起;rotate 策略要自动化。
十二、附录:一张图总结
如果只能记住一件事:身份平台不是成本中心,也不是单纯的安全产品,而是”业务开关”。它决定了多少时间能上线新应用,决定了合规审计能不能过,决定了一个员工离职后多久能被完全清退,决定了 M&A 时两家公司的账号能不能合并。选错或自建不好,这些开关就会卡住业务。
选 SaaS 要敢谈合同,把 exit、数据导出、合规资质写进去。选自建要敢投人,把平台工程岗长期保留,不要让身份平台变成”谁最近有空谁顶一下”的孤岛。两条路都可行,但中间那条”买了又不愿好好对接、自建又舍不得投人”的糊弄路线,永远是最贵的。
十三、附录二:一页速查表
把全文最核心的判断浓缩成一页:
- 问自己的第一个问题不是”哪家便宜”,而是”合规线、生态线、团队能力线给了什么约束”。
- MAU 5 万以下,SaaS 基本胜出;50 万以上,自建成本优势显著;中间带看团队。
- Microsoft 生态 → Entra;非 Microsoft 大企业 → Okta;B2C 快速上线 → Auth0;数据本地化 / 深度定制 → Keycloak;云原生新项目可以看看 Zitadel。
- 无论选谁,抽象出自己的 IdP 对接层,保留迁移的可能性。
- 关键业务逻辑不要写进厂商 DSL,尽量留在自己的 webhook / hook 接收端。
- 把身份平台纳入威胁建模,准备 break-glass,审计日志送到 IdP 外部存储。
- 升级、JWK 轮换、限流、session 一致性这四件事,是事故的高发区,提前演练。
把这张清单贴在评估会议室的墙上,比读 100 页 Gartner 报告更能帮团队做对决定。
十四、参考资料
- Keycloak Release Notes 与 Security Advisories,https://www.keycloak.org/
- Auth0 Pricing 与 Deprecation Notices(Rules/Hooks → Actions),https://auth0.com/
- Microsoft Learn:Entra ID / Entra External ID 文档与 Custom Policy 参考,https://learn.microsoft.com/entra/
- Okta Developer Docs 与 Rate Limit 文档,https://developer.okta.com/docs/reference/rate-limits/
- Okta 2022 Lapsus$ 与 2023 Support Case 入侵事件公开报告。
- CVE-2023-6927、CVE-2023-6134、CVE-2024-1722(Keycloak)。
- Gartner Magic Quadrant for Access Management / IGA(各年度版本)。
- Zitadel、Authentik、FusionAuth 官方架构文档。
- 《Identity and Access Management: Business Performance Through Connected Intelligence》Ertem Osmanoglu。
- Cloudflare:The mechanics of a sophisticated phishing scam and how we stopped it(2022 Okta 事件复盘)。
- 1Password:Notice of recent security incident(2023 Okta HAR 文件事件复盘)。
- KuppingerCole Leadership Compass:Access Management,Customer Identity and Access Management(CIAM)。
- 国家标准 GB/T 22239-2019《信息安全技术 网络安全等级保护基本要求》及相关实施指南。
- Red Hat build of Keycloak Lifecycle 与 Product Documentation。
- Microsoft Security Response Center:Conditional Access and Risk-Based Policies best practices。
上一篇:Keycloak 工程拆解:Realm、Client、Flow 与扩展机制
下一篇:CIAM 架构:面向 B2B / B2C SaaS 的身份平台
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【身份与访问控制工程】IAM 全景:为什么这是高价值赛道
身份与访问控制从一个登录框演进为横跨合规、运维、平台工程和安全的系统工程。本文从一家 SaaS 公司被大客户卡在 SOC 2 合规的真实触发器切入,拆解 IAM、CIAM、IGA、PAM、SSO、目录服务六个子领域的边界,分析 Okta、Entra ID、Auth0、Keycloak、Ping 等主流厂商的定位与落差,给出工程师视角的介入判据与选型路径。
【身份与访问控制工程】Keycloak 工程拆解:Realm、Client、Flow 与扩展机制
从 Quarkus runtime、Infinispan 缓存、数据库 schema,到 Authentication Flow 引擎、SPI 扩展点、multi-site 部署与常见工程坑点,拆解 Keycloak 的真实工程形态与选型边界。
【身份与访问控制工程】SCIM 与账号生命周期:开通、变更、离职自动化
从一起僵尸账号安全事件切入,系统讲透 SCIM 2.0 的资源模型、协议操作、Push/Pull 模式、主流 IdP 差异,以及服务端实现、幂等、软删除、孤儿账户清理等工程落地细节
身份与访问控制工程
从 OIDC、OAuth 2.1、SAML、SCIM 到多租户权限、CIAM、PAM 与身份平台选型——系统拆解现代身份与访问控制的协议、架构与工程实践。