OAuth 2.0 授权码授权
创建时间:2024年07月26日 00:13:06 最后更新:2024年07月26日 09:40:47

授权码授权是 OAuth 2.0 中功能完整、流程严密、应用广泛的授权类型之一。

一句话概述:授权服务验证用户身份之后先发放授权码客户端应用通过授权码访问授权服务获取访问令牌。因为客户端获取访问令牌的过程是在服务器后端进行,所以访问令牌不会暴露,具有较高的安全性。

授权流程

1. 流程示意图

+----------+
| Resource |
|   Owner  |
|          |
+----------+
     ^
     |
    (B)
+----|-----+          Client Identifier      +---------------+
|         -+----(A)-- & Redirection URI ---->|               |
|  User-   |                                 | Authorization |
|  Agent  -+----(B)-- User authenticates --->|     Server    |
|          |                                 |               |
|         -+----(C)-- Authorization Code ---<|               |
+-|----|---+                                 +---------------+
  |    |                                         ^      v
 (A)  (C)                                        |      |
  |    |                                         |      |
  ^    v                                         |      |
+---------+                                      |      |
|         |>---(D)-- Authorization Code ---------'      |
|  Client |          & Redirection URI                  |
|         |                                             |
|         |<---(E)----- Access Token -------------------'
+---------+       (w/ Optional Refresh Token)

2. 步骤解析

(A):客户端引导用户代理(浏览器)到达授权服务器的授权终结点,并携带参数:response_type(code)、client_idredirect_uriscopestate

(B):授权服务器通过用户代理(浏览器)验证资源所有者(用户),并确定资源所有者是否同意客户端授权。

(C):验证资源所有者成功,并且允许授权,授权服务器将用户代理(浏览器)重定向到 redirect_uri,并返回 code 和授权请求的 state

(D):客户端向授权服务器令牌终结点请求令牌,并携带参数:grant_typecoderedirect_uriclient_idsecret(可选)。

(E):授权服务器验证 codeclient_idsecret 是否有效,并验证redirect_uri是否与步骤(C)中一致,如果验证成功,携带 Access Token 将用户代理(浏览器)重定向到 redirect_uri

参数详解

  • response_type:表示响应类型,必选项,此处授权码授权的值固定为 code
  • client_id:表示客户端的ID,必选项
  • redirect_uri:表示重定向URI,可选项。
  • scope:表示申请的权限范围,可选项。
  • state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。用于防止恶意攻击。

案例解析

第三方应用接入微信开放平台为例。

oauth_wechat_login.png

  1. 在第三方应用中点击“微信登陆”,跳转到微信用户授权页面

请求:

https://open.weixin.qq.com/connect/oauth2/authorize
?appid=APPID
&redirect_uri=REDIRECT_URI
&response_type=code
&scope=SCOPE
&state=STATE

参数:

  • appid:网页应用唯一标识
  • redirect_uri:授权成功后重定向的回调链接地址,请使用 urlEncode 对链接进行处理
  • response_type:响应类型,值固定为 code
  • scope:授权范围,由微信公众平台定义,供用户选择的授权范围,有 snsapi_basesnsapi_userinfo 两种
  • state:由客户端生成,并在重定向Uri中会原样返回,用于验证回调请求的合法性,开发者可以填写 a-z A-Z 0-9的参数值,最多128字节。

响应:重定向

REDIRECT_URI
?code=CODE
&state=STATE

code 为微信公共平台返回的授权码

  1. 通过 code 获取 token

请求:

https://api.weixin.qq.com/sns/oauth2/access_token
?appid=APPID
&secret=SECRET
&code=CODE
&grant_type=authorization_code

参数:

  • appid::网页应用唯一标识
  • secret:网页应用密钥
  • code:通过上一步获取的 code 参数(存在有效期,通常设为10分钟,客户端只能使用该码一次,否则会被授权服务器拒绝。该码与客户端ID和重定向URI,是一一对应关系)
  • grant_type:授权类型,值固定为 authorization_code

响应结果:

{
  "access_token":"ACCESS_TOKEN", //网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
  "expires_in":7200,  // access_token接口调用凭证超时时间,单位(秒)
  "refresh_token":"REFRESH_TOKEN", //用户刷新access_token
  "openid":"OPENID",  //用户唯一标识
  "scope":"SCOPE"  //用户授权的作用域,使用逗号(,)分隔
}
  • access_token:表示访问令牌,必选项。
  • token_type:表示令牌类型,该值大小写不敏感,必选项,可以是 bearer 类型或 mac 类型。
  • expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。
  • refresh_token:表示刷新令牌,用来获取下一次的访问令牌,可选项。
  • scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。

特点

示意图中:步骤(A)(B)(C)在前端通道(Front Channel)进行,即通过用户代理(浏览器)实现用户与授权服务器交互;步骤(D)(E)在后端通道(Back Channel)进行,即在客户端(后台)与授权服务器授权终结点和令牌终结点进行交互。

在前端通道发送的交互请求采用 TSL 加密通信,确保请求不会被第三方篡改;在后端通道中执行的操作,第三方法无法拦截,确保获取授权令牌过程的安全。

适用场景

适用于有服务器端的应用程序,如:Web应用、移动应用(有服务端)。

思考

为什么在得到授权码(Authentication Code)之后,还要再访问一次,将授权码换成访问令牌(Access Token)?

因为授权码走前端通道,并不安全,可能被拦截。

这里涉及到两个概念:

  • Front Channel 前端通道:浏览器/移动应用与服务器的通信,安全性相对较低。
  • Back Channel 后端通道:服务器与服务器之间的通信,高度安全的。

通过前端通道获取授权码,然后通过高度安全的后端通道使用授权码获取访问令牌,确保访问令牌的安全发放。