Technical documentation

OAuth 只能给令牌,OIDC 怎么拿到用户邮箱?看 Authorization Code Flow 如何把 Claims 塞进 ID Token

OAuth 只能给令牌,OIDC 怎么拿到用户邮箱?看 Authorization Code Flow 如何把 Claims 塞进 ID Token

OIDC 登录流程通过授权码交换获取 ID Token,将其携带的 Claims 直接作为用户基础档案传递给依赖方,从而完成从单纯授权到身份认证的转化。

OIDC 在 OAuth 基础上如何增加认证能力

OIDC 在 OAuth 2.0 之上构建认证层,核心使命是通过标准 Claims 字段传递终端用户身份信息,解决单纯资源访问无法确认“你是谁”的问题。

很多开发者容易混淆,以为只要用了 OAuth 就能直接拿到用户头像和邮箱。其实,OpenID Connect Core 1.0(2011 年最终文本)早已明确定义:OIDC 是建立在 OAuth 2.0 之上的认证层,其核心使命是通过 Claims 传递终端用户的身份信息 [1]。这不仅仅是术语的更替,更是架构逻辑的根本叠加。

为什么不能把 OIDC 简单理解为“带登录的 OAuth”

OAuth 的核心任务是解决“能否访问资源”的问题,比如允许应用读取你的日历;而 OIDC 则多了一层关键任务:验证终端用户身份并获取基础档案信息 。这种关系就像在现有的物流系统上,额外加了一套严格的身份核验流程。它保留了 OAuth 2.0 的授权交互作为底层基础,同时引入了面向认证与 Claims 的协议语义 [1]。

依赖方的需求因此发生了质的转变。过去只需确认令牌有效即可操作数据;现在需要确认“操作者是谁”。虽然《OIDC Basic Client Implementer’s Guide draft 32》将其描述为 OAuth 2.0 上的身份层,但该文档仅为草案且是 Core 的子集,不能独立于 Core 规范作为证据 。这意味着你不能脱离 Core 规范去理解这个“身份层”,必须回到 OAuth 的授权框架中,看它如何承载新的语义。整个体系由此形成:底层是 OAuth 的授权通道,上层叠加了身份验证逻辑,两者是基础与扩展的关系,而非二选一。

一个常被外行误解的细节在于:许多人认为 ID Token 里的 email 字段是自动获取的,或者像某些第三方登录那样“默认包含所有信息”。实际上,OIDC 协议本身并不强制返回任何具体的用户属性。除非客户端在发起请求时显式地通过 scope 参数声明了如 profile 或 email 的需求,并且授权服务器配置了相应的策略,否则 ID Token 里可能只包含一个 sub(唯一标识符),而没有任何姓名或邮箱。这就是为什么同样的 Authorization Code Flow,在不同厂商(如 Google、Auth0 或自建 Keycloak)的实践中,拿到的数据颗粒度完全不同——这取决于“声明”与“策略”的匹配,而非协议本身的自动行为。

OIDC 登录流程如何获取用户信息的核心路径

OIDC 获取用户信息的核心路径在于利用 Authorization Code Flow 进行令牌交换,将抽象的身份请求转化为包含可信用户数据的身份凭证。

当客户端拿到授权码后,怎么把抽象的“你是谁”变成一份可信的身份档案?关键在于 Authorization Code Flow 中的 Token 交换环节。这一步将单纯的访问许可,转化为了包含用户基础信息的身份凭证 [1]。

从授权码到 ID Token 的交换

流程启动时,客户端先引导用户去授权服务器获得一个临时的授权码 [1]。这个码本身不包含任何用户数据,它只是一张兑换券。真正的转折点发生在后端:客户端拿着这张券,向 Token Endpoint 发起请求。此时,授权服务器不仅会返回用于访问资源的 Access Token,还会吐出一个关键产物——ID Token [1]。

这里有一个关键的分工差异。Access Token 用来告诉资源服务器“你可以访问什么”,而 ID Token 则是用来证明“你是谁”。OIDC 协议在 OAuth 2.0 之上叠加了这层语义,让依赖方能直接通过 ID Token 验证终端用户的身份 。这种设计避免了客户端自己去查询数据库或调用额外的 API 来获取基本信息,所有身份数据都封装在了这个 Token 里。

为了看清不同阶段的数据形态,我们可以对比一下交互前后的状态:

阶段 传递内容 数据性质 接收方角色
授权请求 重定向链接 + 授权码 临时凭证(无用户信息) 授权服务器
Token 交换 ID Token + Access Token 结构化身份数据 + 资源权限 客户端/依赖方
最终使用 Claims (姓名、邮箱等) 终端用户基础档案 依赖方业务逻辑

Claims 如何承载用户档案

ID Token 的结构化数据就是用户信息的载体。它内部包含一组 Claims,比如 name、email 等字段,这些直接构成了终端用户的基础档案 [1]。当依赖方解析这个 Token 时,不需要再问“这个用户叫什么”,Token 里已经写明了答案。

这种机制彻底区分了“资源访问”和“身份认证”。在纯 OAuth 场景下,客户端只能拿到一个令牌去操作数据,却不知道操作者的具体身份细节;而在 OIDC 流程中,Authorization Code Flow 确保了 ID Token 作为认证结果被安全地传递给依赖方 [1]。Claims 不再是零散的信息点,而是经过加密签名的完整身份快照。整个路径就这样跑通了:前端拿到授权码 -> 后端换取 ID Token -> 解析出 Claims -> 建立用户档案。这一套组合拳,让 OIDC 在保留 OAuth 授权能力的同时,补全了登录认证缺失的那一块拼图 。

在实际落地中,不同平台的实现细节也值得注意。例如,Google Identity Services 倾向于将用户画像信息集中在 id_token 中,而部分企业级 Identity Provider(如 Okta 或 PingIdentity)则可能要求依赖方在拿到 ID Token 后,再根据 access_token 去调用 UserInfo Endpoint 以获取更详细的 Profile 信息。这种差异并非协议错误,而是不同厂商对“最小化传输”与“按需获取”策略的不同取舍。理解这一点,能帮助开发者在面对不同供应商时,不再盲目假设“拿到了 Token 就万事大吉”。

ID Token 中的 Claims 如何构成用户档案

ID Token 中的 Claims 字段如姓名、邮箱和唯一标识符,直接拼凑出终端用户的完整身份画像,使依赖方能依据这些数据进行身份验证。

客户端拿到 Authorization Code Flow 交换来的 ID Token,真正的价值不在令牌本身,而在它携带的 Claims。这些字段——name、email、sub——直接拼出了终端用户的身份画像 [1]。依赖方不需要再问“你是谁”,ID Token 已经给出了答案。

Claims 与 OAuth Access Token 的本质区别

Claims 和 Access Token 常被混淆,因为它们在流程中经常成对出现。但两者的使命截然不同。Access Token 是一把钥匙,用来打开受保护的资源接口;Claims 是一份证件,用来证明持有者的身份 [1]。

想象一下:你拿着门禁卡(Access Token)进入办公楼,保安只认卡不认人;但你出示身份证(ID Token + Claims),前台才能确认你是张三还是李四,并记录你的入职信息。OIDC 的核心增量就在这里——它让服务器不仅能授权访问,还能直接读取用户的基础档案数据。这种区分在安全边界上尤为关键。Claims 的传递并非裸奔,而是严格依赖于 OIDC 规范 的签名验证机制 [1]。如果签名校验失败,任何 Claims 内容都不可信。这确保了依赖方拿到的不是伪造的用户名,而是经过授权服务器背书的真实身份结果。

为了更直观地看清这两者的分工,请看下表对比:

维度 Access Token (OAuth) ID Token Claims (OIDC)
核心用途 访问受保护的 API 资源 描述用户是谁及基础属性
典型内容 随机字符串或加密 Payload name, email, sub, picture 等
验证重点 是否拥有操作权限 签名是否有效、数据是否可信
接收对象 后端服务或资源服务器 依赖方应用(前端或后端)
失效后果 无法调用特定接口 无法确认用户身份或建立会话

[1] 表格数据基于 OpenID Connect Core 规范对 Token 功能的定义整理。

从功能定位看,这里获取的是明确的“身份认证结果” [1]。这与单纯的资源访问授权形成了鲜明对照。Authorization Code Flow 的最终产出不仅仅是能调接口的凭证,更是一套完整的用户档案数据。依赖方依据这些 Claims 构建本地账户体系,无需二次询问用户,也无需额外发起查询请求。这就是 OIDC 在 OAuth 之上叠加的身份层带来的直接红利。

实操建议:如何确保获取到准确的邮箱地址? 许多开发者在集成时发现,即使用了 openid email scope,返回的 email 字段有时为空。这通常不是因为协议故障,而是因为用户未授权或平台策略限制。要解决这个问题,建议在代码逻辑中加入明确的判断步骤:首先检查 scope 参数中是否包含了 email 和 profile;其次,在收到 ID Token 后,立即验证 email_verified 字段是否为 true;最后,如果该字段缺失或为假,应主动触发一个“重新授权”或“补充信息”的流程,而不是直接使用空值或默认占位符。这种“防御性编程”能显著降低因数据缺失导致的用户体验问题。

关于 OIDC 流程选型的规范现状与误区

尽管规范保留多种流程,但实际部署中 Authorization Code Flow 是安全首选,盲目套用旧规范指导浏览器或移动端选型极易埋下安全隐患。

OpenID Connect Core 规范里确实同时列出了 Authorization Code Flow 和 Implicit Flow[1]。但这并不代表这两个流程在当下的实际部署中地位等同。规范的存在只是历史遗留的“说明书”,而非当下的“安全指南”。盲目套用旧规范来指导浏览器、移动端或服务间调用的选型,极易埋下隐患[1]。

为什么不建议随意使用 Implicit Flow

Implicit Flow 的设计初衷是为了简化单页应用(SPA)的交互,但它将敏感数据直接放在重定向 URI 的片段(fragment)中传输。这种处理方式让 Token 暴露在浏览器历史记录、服务器日志甚至第三方插件面前,安全性远不如授权码流程。现代开发环境早已转向更安全的方案:Web 端推荐 Authorization Code Flow 配合 PKCE 扩展,移动端也优先采用此路径。

不要看到规范里有某条路就走。核心逻辑在于区分“能力”与“推荐”。OIDC 提供了多种工具,但最佳实践只有一条:除非有极特殊的遗留系统兼容需求,否则应坚决避开 Implicit Flow,聚焦于 Authorization Code Flow 以获取完整的用户档案信息。


FAQ: 常见问题解答

Q: Authorization Code Flow 和 Implicit Flow 的主要区别是什么? A: 主要区别在于安全性。Authorization Code Flow 通过后端交换令牌,不会将敏感 Token 暴露在前端 URL 中,是目前推荐的标准流程;而 Implicit Flow 直接将 Token 返回给前端,存在泄露风险,已不再推荐用于生产环境。

Q: 如何通过 ID Token 获取用户的真实邮箱? A: 在 Authorization Code Flow 完成后,客户端解析收到的 ID Token,其中的 email Claim 即为用户邮箱。前提是用户在授权时同意了该 Scope(如 email),且授权服务器配置了返回该字段的策略。此外,务必检查 email_verified 字段以确保邮箱真实性。

Q: Claims 和 Access Token 可以互换使用吗? A: 不可以。Access Token 仅用于调用受保护的 API 资源,不包含用户身份信息;Claims 是 ID Token 的一部分,专门用于描述用户身份属性。两者在 OIDC 体系中各司其职。

Q: 为什么有时候拿到了 ID Token 却拿不到名字? A: 这通常是因为客户端在发起授权请求时,没有在 scope 参数中包含 profile 范围,或者授权服务器的策略限制了该字段的返回。请检查请求参数及服务端配置,确保显式申请了所需数据的权限。

【金矿素材(事实参考)】 【1.2 OIDC:在授权框架上增加认证语义】 OpenID Connect Core 1.0(纳入勘误集 2 的最终文本,页面标示年份为 2011 年)将 OIDC 表述为建立在 OAuth 2.0 之上的认证能力,并以 Claims 传递终端用户信息[1]。与 OAuth 的有限访问定位相比,OIDC 为依赖方提出了不同的问题:客户端能否基于授权服务器完成的认证来验证终端用户身份,并取得所需的基础档案信息。

这种叠加关系说明,OIDC 不是简单地把 OAuth 的术语换成“登录”。它保留 OAuth 2.0 的授权交互作为基础,同时引入面向认证与 Claims 的协议语义[1]。OIDC Basic Client Implementer’s Guide draft 32 将其描述为 OAuth 2.0 上的身份层,并以基本 Web Relying Party 的授权码流程为范围;该文档是草案且自述为 Core 的子集,不能被当作独立于 Core 的第二份规范证据。

OIDC Core 的目录和认证章节列出 Authorization Code Flow 与 Implicit Flow:前者涉及 Token Endpoint、ID Token 与 Access Token 的处理或验证结构,后者涉及授权端点响应及 Redirect URI fragment 处理[1]。但“规范中存在某流程”与“该流程在截至 2026 年 10 月的部署中仍获推荐”是两个不同判断;现有材料没有提供现行安全最佳实践或后续规范的正文,因而不能据此为浏览器、移动端或服务间调用作出流程选型建议【counter_argument】[1]。

【搜索参考(仅供灵感,不相关的忽略)】 (无搜索结果)

【当前日期】 2026 年 6 月


参考来源

  1. Final: OpenID Connect Core 1.0 incorporating errata set 2 · https://openid.net/specs/openid-connect-core-1_0.html(S级)