开放平台鉴权以及OAuth2.0介绍

OAuth 2.0 协议

  • OAuth是一个开发标准,容许用户受权第三方网站或应用访问他们存储在另外的服务提供者上的信息,而不须要将用户名和密码提供给第三方网站或分享他们数据的内容。
  • OAuth 2.0不兼容1.0。

协议的参与者

  • RO (resource owner): 资源全部者,对资源具备受权能力的人。
  • RS (resource server): 资源服务器,它存储资源,并处理对资源的访问请求。
  • Client: 第三方应用,它得到RO的受权后即可以去访问RO的资源。
  • AS (authorization server): 受权服务器,它认证RO的身份,为RO提供受权审批流程,并最终颁发受权令牌(Access Token)。

受权方式

在开放受权中,第三方应用(Client)多是一个Web站点,也多是在浏览器中运行的一段JavaScript代码,还多是安装在本地的一个应用程序。这些第三方应用都有各自的安全特性。对于Web站点来讲,它与RO浏览器是分离的,它能够本身保存协议中的敏感数据,这些密钥能够不暴露给RO;对于JavaScript代码和本地安全的应用程序来讲,它原本就运行在RO的浏览器中,RO是能够访问到Client在协议中的敏感数据。web

OAuth2.0为了支持这些不一样类型的第三方应用,提出了下面四种受权类型:浏览器

  1. 受权码 (Authorization Code Grant),适用于有server端的应用受权。
  2. 隐式受权 (Implicit Grant),适用于经过客户端访问的应用受权。
  3. 资源全部者密码凭证许可 (Resource Owner Password Credentials Grant),OAuth简化版,经常使用于移动应用认证,称为xAuth。
  4. 受保护资源的客户端受权 (Client Credentials Grant)。
流程 Response Type(第一次请求) Grant Type(第二次请求) 可带Refresh Token 说明
受权码 code authorization_code 常规流程
Implicit token - 适用于纯JS程序
用户认证 - password 客户端高度可信,且受权码流程不方便实施
客户端 - client_credentials 客户端高度可信,拥有被操做资源(自用型),或操做非敏感资源

Authorization Code 受权

1. 受权场景

Authorization code 受权适用于PC,无线客户端等须要和第三方server进行交互的应用场景。使用Authorization code受权,第三方可以集中处理用户的受权请求和受权结果,适用于有server端的应用。安全

2. 受权流程

Authorization code受权模式分为两步,首先获取authorization code,而后用code获取acces token。服务器

示意图:app

     +----------+
     | 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)

 

交互图:性能

  
  +--------+                                           +---------------+
  |        |--(A)------- Authorization Grant --------->|               |
  |        |                                           |               |
  |        |<-(B)----------- Access Token -------------|               |
  |        |               & Refresh Token             |               |
  |        |                                           |               |
  |        |                            +----------+   |               |
  |        |--(C)---- Access Token ---->|          |   |               |
  |        |                            |          |   |               |
  |        |<-(D)- Protected Resource --| Resource |   | Authorization |
  | Client |                            |  Server  |   |     Server    |
  |        |--(E)---- Access Token ---->|          |   |               |
  |        |                            |          |   |               |
  |        |<-(F)- Invalid Token Error -|          |   |               |
  |        |                            +----------+   |               |
  |        |                                           |               |
  |        |--(G)----------- Refresh Token ----------->|               |
  |        |                                           |               |
  |        |<-(H)----------- Access Token -------------|               |
  +--------+           & Optional Refresh Token        +---------------+

 

3. 过程详解

一、获取Authorization Code网站

请求参数加密

  • client_id 必须 分配给应用的appid
  • redirect_uri 必须 受权回调地址,必须和应用注册的地址一致
  • response_type 必须 受权类型,此值固定为“code”
  • state 必须 client端的状态值。用于第三方应用防止CSRF攻击,成功受权后回调时会原样带回。请务必严格按照流程检查用户与state参数状态的绑定。
  • scope 可选 授予权限范围
  • 其余参数

若是用户成功受权,则会跳转到指定的回调地址,并在redirect_uri地址后带上Authorization Code和原始的state值spa

二、经过Authorization Code获取Access Token设计

请求参数

  • client_id 必须 分配给应用的appid
  • grant_type 必须 受权类型,此值为:authorization_code
  • client_secret 必须 分配给应用的secret
  • state 必须 client端的状态值。用于第三方应用防止CSRF攻击,成功受权后回调时会原样带回。请务必严格按照流程检查用户与state参数状态的绑定。
  • redirect_uri 必须 与上面一步中传入的redirect_uri保持一致
  • code 必须 上一步返回的Authorization Code值(必须设定此code的有效时间)

返回参数

  • access_token 必须 受权令牌
  • expires_in 必须 该access_token的有效期
  • refresh_token 可选 在受权自动续期步骤中,获取新的Access_Token时须要提供的参数
  • 其余参数 可选

三、[可选] 权限自动续期,获取access_token

Access_token通常须要根据应用特性设定有效期,过时后须要用户从新受权或采用自动续期的方式。

请求参数

  • grant_type 必须 受权类型,在本步骤中,此值为“refresh_token”
  • client_id 必须 分配给应用的appid
  • refresh_token 必须 第二步返回的refresh_token
  • client_secret 必须 分配给应用的secret

若是受权成功,则会返回和步骤二一样的结果。

Implicit 受权

1. 受权场景

Implicit受权通常适用于没有server端的客户端应用,由客户端发起受权请求,保存和处理access_token,但有些应用(如web应用等)为了提升用户体验,简化受权过程,也会常采用Implicit受权方式(注意,这种受权方式没有返回refresh_token。)

2. 受权流程

示意图:

     +----------+
     | Resource |
     |  Owner   |
     |          |
     +----------+
          ^
          |
         (B)
     +----|-----+          Client Identifier     +---------------+
     |         -+----(A)-- & Redirection URI --->|               |
     |  User-   |                                | Authorization |
     |  Agent  -|----(B)-- User authenticates -->|     Server    |
     |          |                                |               |
     |          |<---(C)--- Redirection URI ----<|               |
     |          |          with Access Token     +---------------+
     |          |            in Fragment
     |          |                                +---------------+
     |          |----(D)--- Redirection URI ---->|   Web-Hosted  |
     |          |          without Fragment      |     Client    |
     |          |                                |    Resource   |
     |     (F)  |<---(E)------- Script ---------<|               |
     |          |                                +---------------+
     +-|--------+
       |    |
      (A)  (G) Access Token
       |    |
       ^    v
     +---------+
     |         |
     |  Client |
     |         |
     +---------+

   Note: The lines illustrating steps (A) and (B) are broken into two
   parts as they pass through the user-agent.

 

交互图:

 
     +----------+
     | Resource |
     |  Owner   |
     |          |
     +----------+
          v
          |    Resource Owner
         (A) Password Credentials
          |
          v
     +---------+                                  +---------------+
     |         |>--(B)---- Resource Owner ------->|               |
     |         |         Password Credentials     | Authorization |
     | Client  |                                  |     Server    |
     |         |<--(C)---- Access Token ---------<|               |
     |         |    (w/ Optional Refresh Token)   |               |
     +---------+                                  +---------------+

 

交互图:

3. 过程详解

请求参数

  • response_type 必须 受权类型,在本步骤中,此值为“token”
  • client_id 必须 分配给应用的appid
  • redirect_uri 必须 受权回调地址,必须和应用注册的地址一致
  • scope 可选 授予权限范围
  • state 必须 client端的状态值。用于第三方应用防止CSRF攻击,成功受权后回调时会原样带回。请务必严格按照流程检查用户与state参数状态的绑定。
  • 其余参数 可选

若是成功受权,则会跳转到redirect_uri指定的回调地址,并带上access_token、expires_in、state以及与应用相关的参数。注意,这种受权方式没有返回refresh_token。

Resource Owner Password Credentials

该受权方式获取access token通常只有一步,相似以下GET/POST请求:https://open.xxx.com/oauth2/access_token?client_id=xxxx&client_secret=xxxxx&grant_type=password&username=xxx&password=xxx

OAuth2.0新特性

  • 服务器角色区分:受权服务器和资源服务器
  • 区别不一样的用户类型、受权场景和受权流程
  • 将token分为频繁传输使用可是有效时长较短的Access Token和用于更新Access Token的Refresh Token
  • 定义多种token,下降资源请求的构造难度
  • 受权过程不签名,可根据须要采用HTTPS加密传输、验证客户端密钥(经过签名)、客户端注册时预先指定callback地址等手段。
  • 明确引入客户端注册流程:肯定Client Type、callback URL以及其它信息
  • 引入可选的state参数,帮助客户端防范CSRF和管理状态
  • 引入scope参数,能够进行受权范围控制
  • token type等可被扩展: bearer(HTTPS), mac(HTTP+sign), etc.

淘宝的OAuth2.0安全控制

  • 只支持HTTPS(bears),不支持签名(签名是走之前老的受权方式)
  • 受权过程指定的callback URL必须与注册的callback URL在同一个域名,或者为um:ietf:wg:oauth:2.0:oob(表示只显示受权码,不回调callback URL)
  • 接口分不一样级别(R1, R2, W1, W2),同一Token对不一样级别接口有不一样的有效期
  • 接口权限划分(item, promotion, user, etc.)

说明 为什么引入authorization_code?

协议设计中,为何要使用authorization_code来交换access_token?这是读者容易想到的一个问题。也就是说,在协议的第3步,为何不直接将access_token经过重定向方式返回给Client呢?好比:

HTTP/1.1 302 Location: https://www.facebook.com/?access_token=ya29.AHES6ZSXVKYTW2VAGZtnMjD&token_type=Bearer&expires_in=3600

若是直接返回access_token,协议将变得更加简洁,并且少一次Client与AS之间的交互,性能也更优。那为什么不这么设计呢?协议文档[1]中并无给出这样设计的理由,但也不难分析:(1) 浏览器的redirect_uri是一个不安全信道,此方式不适合于传递敏感数据(如access_token)。由于uri可能经过HTTP referrer被传递给其它恶意站点,也可能存在于浏览器cacher或log文件中,这就给攻击者盗取access_token带来了不少机会。另外,此协议也不该该假设RO用户代理的行为是可信赖的,由于RO的浏览器可能早已被攻击者植入了跨站脚本用来监听access_token。所以,access_token经过RO的用户代理传递给Client,会显著扩大access_token被泄露的风险。 但authorization_code能够经过redirect_uri方式来传递,是由于authorization_code并不像access_token同样敏感。即便authorization_code被泄露,攻击者也没法直接拿到access_token,由于拿authorization_code去交换access_token是须要验证Client的真实身份。也就是说,除了Client以外,其余人拿authorization_code是没有用的。 此外,access_token应该只颁发给Client使用,其余任何主体(包括RO)都不该该获取access_token。协议的设计应能保证Client是惟一有能力获取access_token的主体。引入authorization_code以后,即可以保证Client是access_token的惟一持有人。固然,Client也是惟一的有义务须要保护access_token不被泄露。 (2) 引入authorization_code还会带来以下的好处。因为协议须要验证Client的身份,若是不引入authorization_code,这个Client的身份认证只能经过第1步的redirect_uri来传递。一样因为redirect_uri是一个不安全信道,这就额外要求Client必须使用数字签名技术来进行身份认证,而不能用简单的密码或口令认证方式。引入authorization_code以后,AS能够直接对Client进行身份认证(见步骤4和5),并且能够支持任意的Client认证方式(好比,简单地直接将Client端密钥发送给AS)。 在咱们理解了上述安全性考虑以后,读者也许会有豁然开朗的感受,懂得了引入authorization_code的妙处。那么,是否是必定要引入authorization_code才能解决这些安全问题呢?固然不是。笔者将会在另外一篇博文给出一个直接返回access_token的扩展受权类型解决方案,它在知足相同安全性的条件下,使协议更简洁,交互次数更少。

相关文章
相关标签/搜索