OIDC IdP(OpenID Connect Identity Provider)是在 OpenID Connect 中负责确认用户身份、执行登录策略并 签发 ID Token 的身份权威服务。
核心问题
平台如果自己保存密码、实现登录、处理 2FA、密码找回、暴力破解锁定和会话风险,就会把认证安全变成每个业务系统都要重复实现的基础设施问题。OIDC IdP 把“这个人是谁、能不能登录、靠什么凭据登录”集中处理,业务平台只信任 IdP 签发的身份声明。
这个拆分的关键边界是:IdP 负责 认证,平台负责 授权。也就是说,IdP 回答“这个用户已经通过身份验证吗”,平台再回答“这个用户进来后能做什么”。
核心对象
| 对象 | 作用 |
|---|---|
| 用户 | 要登录的人,可能使用密码、企业 SSO、WebAuthn、短信或其他凭据 |
| IdP | 认证权威,保存或联邦到用户目录,签发 ID Token |
| 平台后台 | OIDC 客户端,跳转到 IdP 登录,回调后验证 token |
| ID Token | IdP 签名的身份声明,通常是 JWT |
| issuer | IdP 的唯一签发者标识,常配置为 OIDC_ISSUER_URL |
| JWKS | IdP 暴露的公钥集合,平台用它对 ID Token 做 验签 |
核心机制
典型 Web 后台登录流程可以拆成:
- 用户访问平台后台。
- 平台发现没有登录态,把浏览器重定向到 IdP 的授权端点。
- IdP 处理密码、2FA、企业 SSO、账号锁定、风险策略和会话。
- 认证成功后,IdP 通过回调把授权结果交回平台。
- 平台换取或接收 ID Token。
- 平台用 IdP 的 公钥 验证 ID Token 签名,并检查
iss、aud、exp、nonce等声明。 - 平台读取
sub、email、groups等身份信息,再执行 JIT 准入、审批、RBAC 或其他业务授权。
最小验证逻辑可以写成:
metadata = fetch(issuer + "/.well-known/openid-configuration")
jwks = fetch(metadata.jwks_uri)
claims = verify_jwt(id_token, jwks)
require claims.iss == configured_issuer
require claims.aud contains client_id
require now < claims.exp
principal = claims.subverify_jwt 做的是密码学层面的验签和声明校验;principal = claims.sub 之后,是否允许进入后台仍是平台业务决策。
工程用途
- 统一管理员登录:内部系统、监控、CI、Wiki 和后台都接入同一个 IdP。
- SSO 与离职收敛:账号禁用、离职、组变更在 IdP 或企业目录中统一生效。
- 凭据隔离:平台代码不接触密码,只处理 token 和本地权限。
- 可替换身份源:从 Dex staticPasswords 切换到 Keycloak、Auth0 或企业 SSO 时,平台通常只换 issuer、client id、secret 和回调配置。
- 审计分层:IdP 记录“靠什么登录”,平台记录“登录后做了什么”。
边界与常见坑
- IdP 不只是桥接器:Dex、Keycloak 可以桥接 LDAP、SAML、GitHub 或企业 SSO,但它在 OIDC 客户端眼里仍是签发 ID Token 的权威 issuer。
- ID Token 不是访问令牌:ID Token 给客户端证明“用户是谁”,不应拿去调用任意业务 API。
- 验签成功不等于准入成功:还要检查用户是否在允许名单、是否审批通过、是否有角色。
- issuer 必须严格匹配:测试和生产 IdP、内外网 URL、HTTP/HTTPS 混用都可能导致 token 混淆。
- 密钥轮换要支持:平台应按
kid获取 JWKS,不能把单个公钥硬编码到无法更新。 - 授权不能全交给 IdP:角色、租户、审批状态和后台操作权限通常是平台业务模型的一部分。