OAuth 2.0 详解:从授权码到 Access Token,一文搞懂完整流程

举报
yd_232225224 发表于 2026/08/29 18:34:11 2026/08/29
【摘要】 OAuth 2.0 是目前互联网应用中非常常见的一套授权框架。平时使用网站或者 App 时,我们经常能看到“使用 GitHub 登录”“使用 Google 登录”,或者某个应用请求访问自己的头像、邮箱、网盘文件等功能,这些场景背后往往都能看到 OAuth 2.0 的身影。不过严格来说,OAuth 2.0 并不是一个登录协议,它主要解决的是第三方应用的授权问题。也就是说,在不向第三方提供账号密...

OAuth 2.0 是目前互联网应用中非常常见的一套授权框架。平时使用网站或者 App 时,我们经常能看到“使用 GitHub 登录”“使用 Google 登录”,或者某个应用请求访问自己的头像、邮箱、网盘文件等功能,这些场景背后往往都能看到 OAuth 2.0 的身影。

不过严格来说,OAuth 2.0 并不是一个登录协议,它主要解决的是第三方应用的授权问题。也就是说,在不向第三方提供账号密码的情况下,让第三方获得访问部分资源的权限。

为什么需要 OAuth 2.0

假设现在开发了一个第三方应用,需要读取用户 GitHub 账号中的一些信息。最直接的办法当然是让用户输入 GitHub 的账号和密码,然后由这个应用代替用户登录 GitHub 并读取数据。

这种做法的问题很明显。第三方应用一旦拿到了账号和密码,实际上获得的就不只是读取某项数据的权限,而是整个账号的控制权。用户也无法限制这个应用具体能做什么。除此之外,第三方还需要保存用户密码,一旦服务器发生数据泄露,造成的影响也会非常严重。

OAuth 2.0 的思路是让第三方应用不再接触用户密码。当应用需要访问 GitHub 数据时,将用户引导到 GitHub 自己的授权页面。用户在 GitHub 完成登录,并决定是否允许这个应用访问自己的数据。授权成功后,第三方最终会得到一个 Access Token,后续通过这个 Token 调用 GitHub 提供的 API。

这样一来,用户的 GitHub 密码始终只在 GitHub 自己的系统中使用。第三方得到的只是一个受到权限和有效期限制的访问凭据,而且这个凭据还可以被撤销。这就是 OAuth 2.0 相比直接使用账号密码最大的区别。

OAuth 2.0 中的几个角色

OAuth 2.0 的文档中经常会出现 Resource Owner、Client、Authorization Server 和 Resource Server 这几个名词。刚开始看会觉得比较绕,其实放到实际场景里就很好理解。

还是以第三方应用访问 GitHub 为例。用户是 Resource Owner,也就是资源所有者;第三方应用是 Client,它希望获得用户授权;GitHub 中负责用户登录、授权以及签发 Token 的部分属于 Authorization Server;真正保存用户数据并提供 API 的则属于 Resource Server。

Authorization Server 和 Resource Server 在逻辑上承担不同的职责,不过在实际使用中,它们往往都由同一个平台提供,所以开发者通常不需要特别关注服务器具体是怎么划分的。

Authorization Code 授权流程

OAuth 2.0 定义和演进出了多种授权方式,目前 Web 应用中最常见的还是 Authorization Code,也就是授权码模式。

用户在第三方网站点击 GitHub 授权后,网站首先会把浏览器跳转到 GitHub 的授权页面。在跳转过程中,一般会携带 client_idredirect_uriscopestate 等参数。其中 client_id 用于标识申请授权的是哪个应用,redirect_uri 指定授权结束后的回调地址,而 scope 用于声明应用希望获得哪些权限。

用户登录 GitHub 并同意授权之后,GitHub 会将浏览器重新跳转到第三方预先配置好的回调地址,同时附带一个 Authorization Code,例如:

https://example.com/callback?code=abc123&state=xxxx

第三方服务器拿到这个 Code 之后,还不能直接使用它访问 GitHub API,而是需要向 GitHub 的授权服务器发起请求,用 Authorization Code 换取 Access Token。拿到 Access Token 后,才算真正获得了访问相应资源的凭据。

之所以不在浏览器跳转时直接返回 Access Token,是为了避免真正的访问凭据直接暴露在前端跳转过程中。Authorization Code 本身通常具有较短的有效期,而且只能使用一次,即使被意外获取,风险也比直接暴露长期可用的访问凭据要小。

Access Token

Access Token 是 OAuth 2.0 中最常接触到的东西。第三方应用真正访问 API 时,使用的通常就是它。

例如一个比较常见的 HTTP 请求如下:

GET /api/user HTTP/1.1
Host: example.com
Authorization: Bearer xxxxxxxxxxxxx

这里使用的是 Bearer Token。资源服务器收到请求以后,会验证 Token 是否有效、是否已经过期,以及它是否拥有访问当前资源所需要的权限。验证通过之后才会返回对应的数据。

Access Token 虽然不是用户密码,但同样属于敏感凭据。如果一个有效的 Token 泄露,其他人可能直接使用它调用 API,因此实际开发中不能随意把完整 Token 输出到日志、URL 或者公开的代码仓库中。

Access Token 一般还会设置有效期。这样即使 Token 意外泄露,它能够被利用的时间也是有限的。当然,这又产生了另一个问题:Token 过期之后怎么办?

Refresh Token

如果 Access Token 每次过期都要求用户重新登录并授权,实际体验会很差。因此很多 OAuth 2.0 实现还会提供 Refresh Token。

Refresh Token 不用于直接访问业务 API,它的主要作用是在 Access Token 失效后向授权服务器申请新的 Access Token。例如授权服务器可能返回下面这样的内容:

{
    "access_token": "xxxxxxxx",
    "refresh_token": "yyyyyyyy",
    "expires_in": 3600
}

这里的 expires_in 表示 Access Token 的有效时间。当 Access Token 过期之后,客户端可以携带 Refresh Token 请求授权服务器重新签发一个 Access Token,而不需要再次让用户完成整个授权过程。

也正因为如此,Refresh Token 的生命周期往往比 Access Token 更长。一旦 Refresh Token 泄露,攻击者可能持续获得新的 Access Token,所以服务端对 Refresh Token 的存储通常要更加谨慎。

需要注意的是,并不是所有 OAuth 授权都会提供 Refresh Token,是否签发以及如何使用,要看具体平台的实现和授权策略。

Scope 与权限控制

OAuth 2.0 的另一个重要特点是可以限制第三方应用获得的权限,而不是简单地允许或者拒绝整个账号的访问。

这种权限范围通过 Scope 表示。比如一个平台可能分别提供读取用户基本信息、读取邮箱和修改资料等权限。如果第三方应用只需要获取用户头像和昵称,就只申请对应的读取权限,没有必要同时申请修改资料甚至管理账号的权限。

我们平时使用第三方应用时看到的“该应用将获得你的昵称、头像和邮箱”等提示,本质上就是在告诉用户当前应用申请了哪些权限。

Scope 也是 OAuth 2.0 安全模型中很重要的一部分。即使某个 Access Token 泄露,攻击者能够进行的操作仍然会受到这个 Token 权限范围的限制。因此在实际开发中,应该尽量按照最小权限原则申请 Scope,而不是为了方便直接申请所有权限。

state 和 PKCE

实际接入 OAuth 2.0 时,授权地址里经常还能看到 state 参数。这个参数并不是用来描述用户信息或者权限的,而是用于关联一次授权请求和对应的回调。

客户端在发起授权之前生成一个随机的 state 并保存下来,同时将其放入授权请求。授权服务器完成处理后,会在回调时把这个 state 原样带回来。客户端需要检查返回的 state 是否与之前保存的一致,如果不一致,就应该终止后续授权流程。

除了 state,现在实现 Authorization Code 模式时还经常会使用 PKCE,也就是 Proof Key for Code Exchange。

PKCE 的基本做法是在发起授权前生成一个随机的 code_verifier,然后根据它计算出 code_challenge。授权请求中发送的是 code_challenge,等真正使用 Authorization Code 换取 Access Token 时,再提交原来的 code_verifier。授权服务器验证两者之间的关系,确认是同一个客户端发起的请求后才会签发 Token。

这样即使 Authorization Code 在某个环节被截获,攻击者因为没有对应的 code_verifier,也无法直接使用这个 Code 换取 Access Token。对于移动应用、桌面程序和 SPA 这类无法可靠保存客户端密钥的应用来说,PKCE 尤其重要。现在不少 OAuth 服务也已经推荐所有 Authorization Code 客户端使用 PKCE。

OAuth 2.0 和第三方登录的区别

很多人第一次接触 OAuth 2.0,都是因为“GitHub 登录”或者“Google 登录”,所以很容易认为 OAuth 2.0 就是一套第三方登录协议。

其实 OAuth 2.0 本身解决的是授权问题。它关心的是用户是否允许某个应用访问自己的资源,以及这个应用可以访问哪些资源,并不直接定义“如何证明当前用户是谁”。

真正和身份认证关系更加密切的是 OpenID Connect,也就是经常看到的 OIDC。它建立在 OAuth 2.0 之上,增加了身份认证相关的规范,例如引入 ID Token 来携带身份认证结果。

所以 OAuth 2.0 和 OIDC 可以看成两个相关但用途不同的东西。OAuth 2.0 主要负责授权,OIDC 则在这个基础上补充了身份认证能力。实际项目中的“第三方登录”很多采用的是 OAuth 2.0 + OIDC,只不过平时交流时经常被笼统地称为 OAuth 登录。

总结

OAuth 2.0 最主要的作用,是解决第三方应用访问用户资源时的授权问题。相比直接把账号密码提供给第三方,它通过 Access Token 将用户凭据和资源访问权限分离,同时可以利用 Scope 控制权限范围,并通过 Token 有效期和撤销机制进一步降低凭据泄露带来的风险。

在常见的 Authorization Code 模式中,用户首先在授权服务器完成登录和授权,客户端得到一个临时的 Authorization Code,再通过这个 Code 获取 Access Token,最后携带 Access Token 请求真正的资源接口。如果 Access Token 过期,还可以在服务器允许的情况下使用 Refresh Token 获取新的 Token。现在的实现通常还会结合 state、PKCE 等机制提高整个授权过程的安全性。

刚开始接触 OAuth 2.0 时,Authorization Code、Access Token、Refresh Token、Scope 这些概念确实比较容易混在一起。不过实际用过一次之后就会发现,它们本质上都是围绕同一个问题展开的:第三方需要访问用户的数据,但又不应该因此拿到用户的账号密码和全部权限。

把这个问题想明白之后,再去看 GitHub、Google 或者其他开放平台提供的 OAuth 接口,整个授权过程就比较容易理解了。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。