OAuth2.0 授权码模式


1. 综述

OAuth 2.0是一个关于授权的开放网络标准,它定义了四种授权方式,授权码模式(authorization code)是功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器,与”服务提供商”的认证服务器进行互动。

2. 角色

OAuth 定义了4种角色:

  • 客户端(Client):试图访问受保护资源的第三方应用,它需要得到资源拥有者的授权。
  • 资源所有者(Resource Owner):授予客户端访问权限的实体或人。
  • 资源服务器(Resource Server):托管资源所有者信息的服务器。
  • 授权服务器(Authorization Server):是提供给资源所有者使用的服务器,它能批准或拒绝客户端的请求。授权服务器和资源服务器可以是同一个服务器。

3. 授权码模式

3.1 登记第三方应用

在使用 OAuth 授权之前,必须要在授权服务器处登记新的第三方应用,登记后:

  • 授权服务器会设置第三方应用的redirect_uri,这是第三方应用接受授权码的地址;
  • 第三方应用程序会获得一个client_idsecret

3.2 授权过程

3.2.1 总览

sequenceDiagram
	participant 第三方应用
	participant 用户
    participant 授权服务器
    
    第三方应用->>授权服务器: 认证请求
    授权服务器->>用户: 用户授权页面
    用户->>授权服务器: 用户授权
    授权服务器->>第三方应用: 重定向 URI,返回授权码
    第三方应用->>授权服务器: 请求访问令牌
    授权服务器->>第三方应用: 返回访问令牌

3.2.2 认证请求

用户访问第三方应用,第三方应用发出认证请求、调用授权服务器,成功后将用户重定向到授权服务器的授权页面:

GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb 

Host: authorization-server.com

参数:

  • response_type = code:code 是固定值,代表授权类型是授权码登录
  • client_id:平台授予的client_id
  • redirect_uri:表示授权完成后的回调地址;
  • scope:一个或多个范围值,表示请求内容作用域,一般是固定值
  • state:由第三方应用生成的随机字符串,稍后第三方应用将验证该字符串。

3.2.3 用户授权

用户通过填写用户名、密码等方式授权。

3.2.4 重定向 URI

认证通过后,授权服务器调用redirect_uri返回授权码:

HTTP/1.1 302 Found
Location: https://authorization-server.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz

参数:

  • code:授权服务器返回的授权码
  • state:授权服务器返回第一步中第三方应用发送的state,第三方应用要对比 state 值。

3.2.5 请求访问令牌

第三方应用访问授权服务器请求访问令牌(Access Token):

POST /token
grant_type=authorization_code&
code=SplxlOBeZQQYbYS6WxSbIA&
redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET

Host: authorization-server.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

参数:

  • grant_type=authorization_code:authorization_code是固定值,代表授权类型是授权码登录
  • code:上一步获得的授权码
  • redirect_uri:必须与原始链接中提供的重定向URI相同
  • client_id:第三方应用从授权服务器获得的client_id
  • client_secret:第三方应用从授权服务器获得的secret

成功后授权服务器返回访问令牌:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
  "access_token":"2YotnFZFEjr1zCsicMWpAA",
  "token_type":"example",
  "expires_in":3600,
  "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
  "scope":"scope"
}

参数:

  • access_token:表示访问令牌,必选项。
  • token_type:表示令牌类型,可以是bearer类型或mac类型。
  • expires_in:表示过期时间,单位为秒。
  • refresh_token:表示更新令牌,用来获取下一次的访问令牌,可选项。
  • scope:表示权限范围,此项可省略。

3.2.6 用户登录

第三方应用接受上一步授权服务器返回的访问令牌和到期时间,执行用户登录。

4. 授权码模式的变形

以上介绍了授权码模式的实现,但是现实中通常会有一个统一登录平台,用户从统一平台登录后,就能直接访问各个子系统。这需要对授权码模式进行一些改变。

4.1 总览

sequenceDiagram
	participant 用户
	participant 统一登录平台
	participant 授权服务器
	participant 第三方应用
    
    用户->>统一登录平台: 登录
    统一登录平台->>+授权服务器: 验证用户
    授权服务器->>-统一登录平台: 返回校验结果
    统一登录平台->>+第三方应用: 返回授权码
    第三方应用->>+授权服务器: 请求访问令牌
    授权服务器->>-第三方应用: 校验并返回访问令牌
    第三方应用->>-用户: 创建session, 设置cookie, 并返回302响应

4.2 代理登录

在授权码模式的基础上,省略了认证请求过程,直接由授权服务器把授权码发送给第三方应用。因此需要第三方开放代理登录接口。

请求:

GET /sin?code=AFE206obF&callback=rescall

Content-Type:
text/javascript;charset=UTF-8
Host: third-party.com

参数:

  • code:授权码。
  • callback:要求最终返回给用户的jsonp响应函数名,使用jsonp是为了解决跨域问题。

之后第三方应用请求访问令牌、授权服务器返回请求令牌与上节完全一样。

最终给用户的响应:

HTTP/1.1 302 FOUND
Content-Type:
text/javascript;charset=UTF-8
Date:
Thu, 01 Jun 2017 07:33:46 GMT
Server:
Apache-Coyote/1.1
Set-Cookie:
JSESSIONID=F7E3801FCB894A422AD7AC17A6EDCFCF; Path=/iotmgr/; HttpOnly
Set-Cookie:
sessss=456safas; HttpOnly
Transfer-Encoding:
Chunked
Response:
rescall({"respdesc":"success","respcode":"0"})

5 参考

理解OAuth 2.0

OAuth 2 Simplified

The OAuth 2.0 Authorization Framework

Defining Safer JSON-P


 Toc
 Tags