解读Oauth2.0协议

概念

角色

· RO (resource owner): 资源所有者,对资源具有授权能力的人。也就是用户。
· RS (resource server): 资源服务器,它存储资源,并处理对资源的访问请求。如腾讯资源服务器,它所保管的资源就是用户的照片。
· Client: 第三方应用,它获得RO的授权后便可以去访问RO的资源。如网易印像服务。
此外,为了支持开放授权功能以及更好地描述开放授权协议,OAuth引入了第四个参与实体:
· AS (authorization server): 授权服务器,它认证RO的身份,为RO提供授权审批流程,并最终颁发授权令牌(Access Token)。读者请注意,为了便于协议的描述,这里只是在逻辑上把AS与RS区分开来;在物理上,AS与RS的功能可以由同一个服务器来提供服务。

授权类型

OAuth为了支持这些不同类型的第三方应用,提出了多种授权类型,下面介绍的是使用最广泛也是最复杂的一种授权方式-“授权码”。

流程

OK,经过上面举例后对Oauth授权流程有了一个大致了解,我们抽象一下整个流程
20171017150817503899307.png

(1) Client请求RO的授权,请求中一般包含:要访问的资源路径,操作类型,Client的身份等信息。
(2) RO批准授权,并将“授权证据”发送给Client。至于RO如何批准,这个是协议之外的事情。典型的做法是,AS提供授权审批界面,让RO显式批准。这个可以参考下一节实例化分析中的描述。
(3) Client向AS请求“访问令牌(Access Token)”。此时,Client需向AS提供RO的“授权证据”,以及Client自己身份的凭证。
(4) AS验证通过后,向Client返回“访问令牌”。访问令牌也有多种类型,若为bearer类型,那么谁持有访问令牌,谁就能访问资源。
(5) Client携带“访问令牌”访问RS上的资源。在令牌的有效期内,Client可以多次携带令牌去访问资源。
(6) RS验证令牌的有效性,比如是否伪造、是否越权、是否过期,验证通过后,才能提供服务。

实践

第三方应用通过Oauth授权访问用户QQ服务资源

20171017150817479552930.png

A1-A3: 用户访问第三方应用,第三方应用发起应用授权(此时已经是qq的页面了),用户输入账号密码进行授权
B: 认证服务器响应第三方应用并同时返回code码
C: 第三方应用向授权服务器发起授权请求,此时需要携带code、第三方应用从腾讯处获取的client_id及secret_key
D: 授权服务器返回access_token
F: 第三方应用拿到access_token就可以向资源服务器请求资源了

facebook获取google授权示例

20171017150817571275315.png

FAQ

1.为何引入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

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

参考

帮你深入理解OAuth2.0协议
mooc视频

资料1 资料2 资料3 资料4