参考 rfc6749

一、引文

在我们日常生活中,应用到授权的地方很多,比如支付宝授权访问一些个人信息,微信授权访问一些个人隐私信息,百度云打印照片,我们需要向第三方授权访问我们的一些隐私信息,传统的方法就是我们将自己的用户名和密码告诉第三方,这样的话,第三方应用就可以登录读取我们的隐私信息了,但这样做有些问题

  1. 第三方应用为了后续服务,会保存我们的用户名及密码,这样很不安全
  2. 我们不能限制第三方应用的权利范围和有效期
  3. 我们可以通过手动将密码修改收回某个第三方的权利,但这样会导致之前授权的其他第三方服务都会失效
  4. 只要一个第三方服务被破解,我们的用户名密码就有泄露的风险
  5. 单纯的密码登陆并不安全,增加难度又会影响第三方服务获取授权信息的难度

Oauth的出现可以解决以上问题

二、部分名次解释

(1) third-party application 第三方服务,下文中又称“客户端”client,也就是上文说的第三方服务

(2) http service http服务提供商,本文中简称“服务提供商”,也就是上文说的支付宝,微信,百度云

(3) resource owner 资源所有者,下文中又称“用户”user

(4) user agent 用户代理,下文中指浏览器

(5) authorization server 授权服务器,即服务提供商专门用来处理授权的服务器

(6) authentication server 认证服务器,即服务提供商专门用来处理认证的服务器(发放令牌)

(7) resource server 资源服务器,即服务提供商存放用户资源的服务器,它与授权服务器,认证服务器可以是同一台服务器,也可以是不同的服务器

三、Oauth思路

Oauth在客户端与服务提供商之间,设置了一个授权层(authorization layer),客户端不能直接登录服务提供商,只能登录授权层拥有有限权限。对服务提供商来说,以此可以分隔开用户和客户端,客户端登录授权层所使用的令牌(token)与用户的密码没有关系,用户在登陆的时候,还可以指定授权层令牌的权限范围和有效期。客户端登录授权层后,服务提供商根据令牌的权限以及有效期向客户端开放有限用户资源。

四、运行流程

Oauth2.0的运行流程如下,参考rfc6749 1.2

步骤概述

  • (A)用户打开客户端,客户端要求用户给予授权
  • (B)用户同意给予客户端授权
  • (C)客户端使用上一步获得的授权许可,向认证服务器申请令牌
  • (D)认证服务器对客户端进行认证以后,确认无误,发放令牌
  • (E)客户端使用令牌向资源服务器申请获取资源
  • (F)资源服务器确认令牌,无误后向客户端开放资源

 以上6个步骤中,B是关键,即用户如何给予客户端授权过程,有了这个授权,客户端就可以拿到令牌,进而用令牌访问资源

五、客户端授权模式

客户端得到用户授权(authorization grant),才能获得令牌(access token),oauth2.0定义了4种授权方式,见rfc6749 1.3.x

  •  授权码模式(authorization code)
  • 简化模式(implicit)
  • 密码模式(resource owner password credentials)
  • 客户端模式(client credentials)

六、授权码模式 见rfc6749 4.1

授权码模式(authorization code)相比其他模式是功能最完整,流程最严密的授权模式 ,它的特点事通过客户端的后台服务器与服务提供商的授权服务器进行交互

 

步骤概述

  • (A)用户访问客户端,客户端将用户导向授权服务器
  • (B)用户选择是否给予客户端授权
  • (C)假设用户给予授权,授权服务器将用户导向客户端事先指定的重定向url(redirection url),同时附上授权码
  • (D)客户端收到授权码,附上早先的重定向url,向认证服务器申请令牌,这一步是在客户端后台服务器完成,对用户不可见
  • (E)认证服务器核对授权码与重定向url,确认无误,向客户端发送访问令牌(access token)和更新令牌(refresh token)

A步骤中,客户端需要提供以下参数

  • response_type 授权类型,必选项,固定值code
  • client_id 授权服务器标识客户端的id,这个id是客户端之前向授权服务器注册时服务器分发给这个客户端的,id是唯一的,必选项
  • redirect_uri 授权服务器重定向的url,可选项
  • scope 申请的权限范围,可选项
  • state 传到授权服务器,授权服务器重定向到客户端的时候会将该参数原封不动传回来,推荐选项,可用来防止csrf(cross-site request forgery跨站请求伪造)

比如

C步骤中,服务器重定向到客户端,包含以下参数

  • code 授权码,该码的有效期应该短一些,推荐设置10分钟,客户端只能使用一次,如果认证服务器发现该码被使用不止一次,应该撤销之前和这个码相关的令牌或服务
  • state 之前客户端请求授权中包含这个参数,会原封不动传回来

比如

D步骤中,客户端向认证服务器申请令牌,包含以下参数

  • grant_type 授权模式,必选项,固定值authorization_code
  • code 授权码,必选项,之前从授权服务器拿到的授权码
  • redirect_uri 重定向url,必选项,必须与步骤A中的该参数值相同
  • client_id 客户端id,必选项

比如

E步骤中,认证服务器如果认证通过,http返回中包含以下参数

  •  access_token 访问令牌,必选项
  • token_type 令牌类型,必选项
  • expires_in 过期时间,单位为秒
  • refresh_token 更新令牌,用来获取下一次的访问令牌 

比如

在用户向认证服务器申请令牌的时候,认证服务器通过client_id,client_secret(客户端注册的时候被分配的)判别客户端的真实性

七、简化模式 见rfc6749 4.2

 简化模式(implicit)不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,调过授权码这个步骤。所有步骤在浏览器中完成,令牌对访问者可见,且客户端不需要认证

步骤如下

  • (A)客户端将用户导向认证服务器
  • (B)用户决定是否给予客户端授权
  • (C)用户给予授权,认证服务器讲用户导向客户端指定的重定向url,并在url的fragment(段)部分包含访问令牌
  • (D)浏览器向资源服务器发出请求,请求中不包含上一步收到的fragment
  • (E)资源服务器返回一个网页,网页中包含可以从fragment中提取访问令牌的脚本
  • (F)浏览器执行上一步获得的脚本,提取出令牌
  • (G)浏览器将令牌交给客户端

A步骤中,客户端发出的http请求包含以下参数

  • response_type 授权类型,必选项,固定值token
  • client_id 客户端id,必选项
  • redirect_uri 重定向url,可选项
  • scope 权限范围,可选项
  • state 同授权码模式A步骤

比如

C步骤中,认证服务器重定向客户端,包含以下参数

  • access_token 访问令牌
  • token_type 令牌类型
  • expires_in 过期时间,单位秒
  • scope 权限范围
  • state 同授权码模式步骤E

比如

八、密码模式 见rfc6749 4.3

密码模式(resource owner password credentials grant)中,用户向客户端提供自己的用户名和密码,客户端使用这些信息,向服务商提供商索要授权。在这种情况下,用户必须把自己的密码给到客户端,但客户端不得存储密码,这通常建立在用户对客户端高度信任的基础上,比如客户端是操作系统的一部分或者是权威公司的产品,认证服务器只有在其他模式不可行的情况下,才考虑这个模式

步骤如下

  • (A)用户向客户端提供用户名和密码
  • (B)客户端将用户名和密码发到认证服务器,请求令牌
  • (C)认证服务器确认无误后,向客户端提供访问令牌

B步骤中,客户端发出http请求,包含以下参数

  • grant_type 授权类型,必选项,固定值password
  • username 用户名,必选项
  • password 用户密码,必选项
  • scope 权限范围,可选项

比如

C步骤中,认证服务器向客户端发送访问令牌,例子如下

整个过程,客户端不允许保存用户密码

九、客户端模式 见rfc6749 4.4

客户端模式(client credentials grant)指客户端以自己的名义向服务提供商进行认证,严格意义上,这不属于oauth框架索要解决的问题,在这种模式下,用户直接向客户端注册,客户端以自己的名义要求服务提供商提供服务,其实不存在授权问题

步骤如下

  • (A)客户端向认证服务器进行身份认证,请求一个令牌
  • (B)认证服务器确认无误后,向客户端提供访问令牌

A步骤中,客户端发出http请求,包含以下参数

  • grant_type 授权类型,必选项,固定值client_credentials
  • scope 权限范围,可选项

如下

认证服务器必须以某种方式,验证客户端身份

B步骤中,认证服务器向客户端发送访问令牌,例子如下

十、更新令牌 见rfc6749 6

如果用户访问的时候,客户端令牌已过期,则需要使用更新令牌申请一个新的访问令牌

客户端发出更新访问令牌的请求,参数如下

  • grant_type 授权模式,必选项,固定值refresh_token
  • refresh_token 早前收到的更新令牌,必选项
  • scope 申请授权范围,不可以超出上一次申请的范围,如果省略,则与上一次一致

如下

以上内容根据翻译文档以及rfc原文综合记录