OpenID Connect(OIDC)深度解析:OAuth 2.0 之上的身份认证层

协议详解 · 2026-08-23

为什么需要 OIDC?

OAuth 2.0 解决了「授权」问题——应用如何代表用户访问资源。但它留下了一个关键空白:身份认证。

想象一下这个场景:用户登录了某电商平台,获得了一个 Access Token。平台后端用这个 Token 调用了支付服务,支付服务返回了用户信息。但支付服务怎么知道这个用户是张三还是李四?OAuth 2.0 的 Access Token 只携带权限信息,不携带用户身份信息。

这就是 OpenID Connect(OIDC)要解决的问题。OIDC 是 OAuth 2.0 之上的身份认证层,由 OpenID Foundation 维护,核心规范定义在 RFC 7519(JWT)、RFC 7591(动态客户端注册)以及 OIDC Core 1.0 规范中。

OIDC 的核心组件

OIDC 体系包含四个核心概念:

CODE
┌─────────────────────────────────────────────────────────────────────┐
│                        OIDC 核心组件架构                              │
├──────────────────┬──────────────────────────────────────────────────┤
│ 角色             │ 说明                                            │
├──────────────────┼──────────────────────────────────────────────────┤
│ End-User         │ 最终用户(需要登录的人)                          │
│ Relying Party    │ 依赖方,即使用 OIDC 的服务(App/网站)           │
│ OpenID Provider  │ 身份提供者(OP),负责认证和签发 Token            │
│ User Agent       │ 浏览器或移动客户端                               │
└──────────────────┴──────────────────────────────────────────────────┘

ID Token:OIDC 的核心创新

OAuth 2.0 只有 Access Token(权限凭证)和 Refresh Token(续期凭证)。OIDC 引入了第三个角色:ID Token。

ID Token 是一个 Signed JWT,包含以下核心声明:

声明必填说明
iss✓Issuer,身份提供者标识符
sub✓Subject,用户的唯一标识
aud✓Audience,预期接收方(RP 的 client_id)
exp✓过期时间
iat✓签发时间
auth_time条件必填用户实际认证时间
nonce条件必填认证请求中的随机数,防止重放
at_hash条件必填Access Token 的哈希,绑定两者

UserInfo 端点:补充用户属性

ID Token 只携带少量声明(最多 10 个)。如果需要更多用户信息,OIDC 定义了 UserInfo 端点——一个独立的 HTTPS 接口,RP 携带 Access Token 去查询完整用户资料。

认证流程:授权码流程(Authorization Code Flow)

这是 OIDC 最核心、最常用的流程。完整的交互序列如下:

关键安全设计:state 参数

state 参数用于防止 CSRF 攻击。OP 响应时必须原样返回该值,RP 需验证两者一致。

关键安全设计:nonce 参数

nonce 防止 ID Token 重放攻击。每次认证请求 OP 必须返回相同的 nonce,RP 验证匹配。

其他认证流程

隐式流程(Implicit Flow)—— 已废弃

CODE
GET /authorize?response_type=token&id_token=xxx&state=...

早期用于 SPA(单页应用),将 Token 直接暴露在 URL fragment 中。已被 RFC 9207 标记为 deprecated,不应在新系统中使用。

混合流程(Hybrid Flow)

支持同时获取 Code 和 Token,适合需要部分即时响应的场景。但由于实现复杂且安全风险较高,当前也不推荐。

设备授权流程(Device Authorization Grant)

用于无键盘设备(电视、IoT):

CODE
1. 设备请求授权:
   POST /device_authorization
   → 返回 device_code + user_code(如 ABCD-1234)+ verification_uri

2. 用户在其他设备上打开 verification_uri,输入 user_code

3. 设备轮询 /token,直到用户授权完成

发现机制:.well-known/openid-configuration

OIDC 定义了标准化的发现端点。OP 在 .well-known/openid-configuration 路径下暴露所有端点 URI 和协议能力:

RP 通过调用此端点自动发现所有必要信息,无需硬编码配置。

Scopes 与 Claims

标准 Scope

Scope含义常见 Claims
openid必需,标识 OIDC 请求-
profile基础用户资料name, given_name, family_name, picture
email邮箱地址email, email_verified
phone电话号码phone_number, phone_number_verified
address地址信息formatted, street_address, locality

自定义 Scope

OP 可定义私有 scope,如 read:orders、write:payments。建议最小化授权——只请求需要的 scope。

OIDC 标准 Claims

Claim数据类型描述
substring用户唯一标识(Opaque,不应泄露)
namestring全名
given_namestring名字
family_namestring姓氏
middle_namestring中间名
nicknamestring昵称
preferred_usernamestring偏好用户名
profileURI用户资料页 URL
pictureURI头像 URL
websiteURI个人网站
emailstring邮箱
email_verifiedboolean邮箱是否已验证
genderstring性别
birthdatestring出生日期(YYYY-MM-DD)
zoneinfostring时区(IANA 格式)
localestring语言(BCP 47 格式)
phone_numberstring电话号码
phone_number_verifiedboolean电话是否已验证
addressobject地址对象
updated_atnumber资料最后更新时间

与 OAuth 2.0 的核心区别

维度OAuth 2.0OIDC
核心目的授权(Access Token)认证(ID Token)
Token 类型Access TokenAccess Token + ID Token + Refresh Token
用户信息不定义通过 ID Token + UserInfo 端点
发现机制无标准.well-known/openid-configuration
会话管理无标准Front/Back-channel Logout
适用范围资源授权身份认证
重要认知:OIDC 不是替代 OAuth 2.0,而是叠加在 OAuth 2.0 之上。所有 OIDC 实现都基于 OAuth 2.0 的 grant type 和 token 端点。

安全最佳实践

1. 始终使用 PKCE

即使你的应用是"机密客户端"(有后端服务器),也必须使用 PKCE。2019 年 OWASP 将 PKCE 标记为所有 OAuth 2.0 实现的必备措施。

2. 验证 ID Token 签名

使用 OP 发布的 JWKS(JSON Web Key Set)验证签名:

  • 不支持 RS256 时,拒绝 Token
  • 不要硬编码公钥——定期刷新 JWKS 缓存
  • 注意 JWKS 中可能包含多个 key_id,正确匹配

3. 验证 nonce

每次认证请求生成唯一的随机 nonce,验证 ID Token 中的 nonce 字段完全匹配。防止 ID Token 重放攻击。

4. 使用 Authorization Code + PKCE 流程

隐式流程和 Hybrid 流程均已 deprecated。新系统只应使用 Authorization Code Flow(配合 PKCE)。

5. 最小化 Scope 请求

只请求应用实际需要的 scope 和 claims。过度请求会降低用户体验并增加隐私风险。

6. 验证 state 参数

防止 CSRF 攻击——必须验证 OP 返回的 state 与请求时一致。

7. 检查 at_hash

当 ID Token 与 Access Token 同时返回时,验证 at_hash 确保两者绑定,防止令牌替换攻击。

国密适配:SM2 + SM3 的 OIDC 实现

OIDC 标准假设使用 RSA/ECDSA 签名和 JWT 格式。国密场景下的适配方案:

方案一:SM2 签名 JWT(SM2-JWT)

将传统 JWT 的 alg 字段替换为 SM2 相关值:

  • ES256 → SM2WithSM3(标识符:1.2.156.10197.1.501)
  • RS256/ES256 签名算法替换为 SM2 签名

方案二:ID Token 使用国密证书

在 ID Token 的 jwk 字段中嵌入 SM2 公钥证书(X.509 格式),通过国密 JWKS 端点分发。

方案三:国密 TLS 隧道

使用 GM/T 0024(国密 SSL/TLS 协议)建立 OP 与 RP 之间的安全通道,ID Token 传输层使用国密算法保护。

实际挑战

  • JWKS 扩展:当前 JWKS 规范(RFC 7517)仅支持 RSA/EC 密钥,SM2 密钥的表示需要扩展
  • 客户端库:主流 OIDC 客户端库(auth0、okta、identityserver)对 SM2 支持有限
  • 浏览器兼容性:浏览器原生不支持 SM2 签名验证,需后端代理
建议:在国内落地时,优先采用支持 SM2 的国密身份提供商(如基于 Tongsuo/BabaSSL 的实现),而非强行适配国际标准。

相关实践

参考

  • OpenID Connect Core 1.0: https://openid.net/specs/openid-connect-core-1_0.html
  • OAuth 2.0 (RFC 6749): https://datatracker.ietf.org/doc/html/rfc6749
  • JWT (RFC 7519): https://datatracker.ietf.org/doc/html/rfc7519
  • OAuth 2.1 Security BCP (RFC 9700): https://datatracker.ietf.org/doc/html/rfc9700
  • GM/T 0024-2023《SSL VPN 技术规范》— 国密 TLS 协议
  • GM/T 0015-2023《数字证书格式》— 国密 X.509 证书规范