安全系列之OAuth2协议

前言

OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版。

全面的OAuth协议规约的制定可见OAuth1.0OAuth2.0的官方文档,不过OAuth2.0并不向前兼容,所以一般我们常谈论的OAuth指的是用于"下一代用户验证和授权"的标准OAuth2.0。国内关于OAuth2.0的通俗解释是阮一峰老师的开发者手册,OAuth协议本身是一个不算简单的认证协议,之所以会日趋流行是因为它建立在了客户端开发者的简易性上,符合现阶段大平台小程序的应用发展趋势。

 

一,初见OAuth

关于OAuth的应用场景,阮老师在RFC6749的基础上已经做了很好的解释。

OAuth本身解决的是授权的问题,也就是第三方应用想要获得对于访问该用户某些资源的权限。这里再举个例子:随着巨头公司大平台的发展,小应用在各个场所慢慢普及开来,往往去一家饭馆吃饭就可以使用微信应用支付。你掏出手机扫描二维码,微信登陆小程序的过程中就会产生问题,饭馆是在微信平台上的第三方应用,它需要从微信平台上获取你的信息来在自己的服务器上建立session,也就是建立你这个用户。

如何创建服务器session来证明你是你呢,之前往往是用用户名密码的方式,即你自己想一个用户名来标识你,然后搭配上你凭空想出的一串密码作为value,下次登陆的时候提供用户名让服务器找到你的身份信息,然后输入密码向服务器确认你的身份,就可以登陆系统完成点餐了。

但这种方法有弊端,随着应用越来越多,你不能让用户针对每一个应用都凭空想一个密码,而如果每个密码都相同也太不安全了,稍不留意,一点击破全员崩溃。而且在点餐这个场景中,可能我只需要提供头像和微信用户名就行,不需要让他通过密码就可以获得全部的资源。而微信更不能跳过授权这一环节直接赋权给第三方应用,微信只是饭馆程序的容器,可以负责管理但没必要帮用户承担所有的风险。所以我们要走授权这一环节,而且不想让第三方知道我的密码,也不想用密码去认证。

我们就可以使用令牌(token)这种有时效性,可以限制资源范围的方式走对第三方应用授权这一环节。

 

二,OAuth入门

如何用OAuth的方式完成授权这一环节?

安全系列之OAuth2协议

这是官方制定的OAuth协议流程图,了解了出现的这几个角色就会对OAuth有一个全局的理解。可以看到整张图其实是以最左边的client为中心,这里的client就是第三方应用的OAuth client,也就是上边例子中的饭馆应用。

对于你来说可能最多看到两个实体:微信应用和饭馆应用。但对于第三方应用来说,它看到的时间可能是资源拥有者,授权服务器,资源服务器。

Resource Owner就是正想要点餐的你,只不过你的头像和用户名信息存在了微信,所以微信也是你的信息的资源拥有者。

Authorization server是平台应用管理授权的服务器

Resource Server是存储用户信息的资源服务器

A. 第三方应用向你请求获得你头像以及位置信息等等信息的权限,并在你的手机上弹了个小框

B. 你点击确认授权,表示你同意这个第三方应用知道它想知道的信息

C. 这个第三方应用向授权服务器发送请求告诉AS,我已经获得授权(这里通常是重定向过去)

D. 授权服务器通过授权逻辑,并给client一个用于访问资源的token

E. client把token发给RS资源服务器

F. 资源服务器获得token,把token请求的保护资源交给client

这一循环过后,client获得了你的身份和地址信息,你就可以点餐了。然而这一套流程中涉及的东西还有很多需要了解。

 

三,走进OAuth

OAuth授权(AS对client授权)共4种方式:

1. 授权码方式

常用于常见的各种有前后端具体的应用,授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。

2. 隐藏式

有些 Web 应用是纯前端应用,没有后端。这时就不能用上面的方式了,必须将令牌储存在前端。RFC 6749 就规定了第二种方式,允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤,所以称为(授权码)"隐藏式"(implicit)

3. 密码式

如果你高度信任某个应用,RFC 6749 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为"密码式"(password)。

4. 凭证式

最后一种方式是凭证式(client credentials),适用于没有前端的命令行应用,即在命令行下请求令牌

RFC 6749针对不同方式制定了认证请求和答复报文的使用字段,感兴趣可以去查一下。

以第一种授权码方式为例,还是点餐的场景,AS和resource server都归到OAuth server范畴,以使用者的视角看整个流程:

安全系列之OAuth2协议

之后用户再想登陆第三方应用(OAuth client),在token还有效的情况下,就可以直接向第三方应用发请求,第三方应用通过token直接向resource server拿数据就好了。

 

四,使用OAuth

很遗憾的是把这些流程摸清之后,如果想使用这套流程并不容易,要根据不同系统不同框架,遵循OAuht协议规约去处理。

OAuth token

OAuth 把token分为access token和refresh token,access token就是让client取得资源的令牌,可以使用它登陆并获取资源;同时OAuth也支持client使用refresh token自己刷新access token的周期,这样client就不必频繁地向server请求授权码。

而OAuth token的种类也有Bearer token和mac token。Bearer Token配置文件带来了简化的身份验证方案.具有承载令牌的任何用户都可以使用它来访问相关资源(不证明拥有加***)。MAC(Message Authentication Code)令牌配置文件定义了HTTP MAC访问认证方案,提供了一种通过对请求进行部分加密验证来生成经过身份验证的HTTP请求的方法,包括HTTP方法,请求URI和主机.每个访问令牌类型定义指定与access_token响应参数一起发送到客户端的附加属性(mac_key,mac_algorithm).

token一般包装在http报文头中使用,不过也可以放到url获报文内容中。

OAuth单点登录

单点登录的含义是我在一个OAuth client登录之后,再登陆同一个OAuth server管理下的其他client时就不需要再授权,直接生成其他client中用户的session以简化登录流程。这个使用OAuth同样可以实现。

使用OAuth token

token可以让client登陆到resource server获取资源,同样自己用curl也可以获取到相应的资源。

比如A 网站拿到令牌以后,就可以向 B 网站的 API 请求数据了。
此时,每个发到 API 的请求,都必须带有令牌。具体做法是在请求的头信息,加上一个Authorization字段,令牌就放在这个字段里面。
curl -H "Authorization: Bearer ACCESS_TOKEN" \
"https://api.b.com"

不得不说OAuth是一套完整的支持授权第三方的协议,不过也有相应的问题,OAuth协议也有相应的措施,包括授权码的定义,token的参数,第三方攻击的处理等等。相应自己完成系统也需要按照自己使用的框架Spring security,shiro等等去做相应session生命周期和url拼接的管理。

 

参考:

http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html