大话Oauth2.0(二)、标准流程下的Oauth2组件及通信
首先祝大家五一节日快乐!
Oauth2.0协议的核心内容是,第三方软件如何获取访问令牌,以及如何利用这个访问令牌代表资源拥有者访问受保护的资源。在这篇文章中我们从Oauth2的组件和组件间的通讯讲起。
1、Oauth2组件
一个标准的Oauth2.0共包含四个组件,如下图所示,分别是资源拥有者、第三方软件、授权服务、资源服务。资源拥有者是Oauth2流程的发起者,也是第三方软件的使用者;第三方软件,在Oauth2里面官方的名称叫做客户端,现实世界中其实就是平台之外的第三方软件;授权服务,提供授权码、访问令牌;资源服务,提供WEB API以便接收第三方软件的访问请求。授权服务和资源服务都是平台(比如微信开放平台、淘宝开放平台、京东开放平台等)一方提供的服务。
目前这四个组件暂时没有发生任何通信,仅仅是展示了重要的四个Oauth2组件而已。这篇文章我们要描述的是标准的Oauth2流程,之所以称为标准的流程,也是Oauth2的规范性流程,这个流程中包含了授权码和访问TOKEN。这个规范性的流程规定了要通过两次URI重定向。为什么要通过URI重定向?而且为什么需要两次?接下来我们会去详细分析解答。
2、Oauth2通信
2.1、第三方软件和授权服务之间的通信
Oauth的最原始背景就是解决WEB应用下的授权的安全问题,因此一定不能缺少浏览器的参与。对于非标准条件下的Oauth流程在后续的文章中我们也会有讲述,那个时候可能有的场景是不需要浏览器的。现在我们在叙述的是标准场景下的Oauth使用。
Oauth组件间的通信包括前端通信和后端通信,前端通信就是组件之间的需要交互的信息数据在浏览器里面流转,后端通信就是组件之间需要交互的数据信息通过WEB SERVER之间流转。实际上只有标准场景下的Oauth2流程才会既使用前端通信又使用后端通信,这点在介绍非标准场景下的Oauth使用的时候也会去分析,大家先记下来。
资源所有者A要授权正在使用的第三方软件来能够访问A在平台上受保护的资源,那么A通过浏览器首先访问的是第三方软件的URI地址,此时第三方软件遵循Oauth2.0的协议并按照平台的要求拼接授权URL(参照大话Oauth2.0(一)从概念到实践),将用户引导到平台的授权页面,这个时候发生了第一次URI重定向。A点击了授权页面上的授权按钮,平台一方的授权服务器会对当前的用户进行身份验证,如果身份合法会生成一个CODE也就是我们常说的授权码,然后将这个CODE重定向回第三方软件的CALLBACK URI上(这个CALLBACK URI是拼接授权URI的时候就传过来了),这个时候发生了第二次URI重定向。第一次重定向好理解,用户在使用浏览器访问第三方软件的URI地址,第三方软件需要做引导。第二次重定向为什么也需要呢,通过WEB SERVER直接OUT PRINT回第三方软件的服务器不就可以了吗,如果仅仅是返回这个CODE值当然可以,而且这样还更安全。但是不要忘记了用户还在浏览器上面等着呢,如果将CODE的值直接写回到第三方软件的WEB SERVER上,就会把浏览器上的用户旁路了,因此还必须进行第二次重定向。至此获取CODE的流程都是通过前端通信进行交互的。
在第三方软件获取到CODE之后,同样遵循Oauth2.0的协议并按照平台的要求,会发起一个HTTP POST请求到授权服务器,去访获取ACCESS TOKEN(访问令牌),这个HTTP请求中包含了平台一方事先给第三方软件分配好的client_id和client_secret,这样ACCESS TOKEN的数据传递就是在两个WEB SERVER之间的交互了。至此获取访问令牌的流程是通过后端通信进行交互的,另外再加上HTTPS的保护,ACCESS TOKEN的获取变得更安全了。
以上交互通信如下图所示。
我们还会思考另外一个问题,为什么标准流程下需要先获取CODE,然后再通过CODE获取ACCESS TOKEN呢?这个原因可以结合前端通信环节中的必须经过两次浏览器重定向的描述,如果没有获取CODE这个流程,直接将ACCESS TOKEN重定向回浏览器,无疑这会将访问令牌暴露出去带来安全上的问题。
2.2、第三方软件和资源服务之间的通信
在第三方软件获取到访问令牌之后通过WEB API的方式请求资源服务器,来访问资源所有者的数据。请求的时候要带上第三方软件的client_id、client_secret和acces_token。资源服务器则需要判断来访的第三方软件的合法性。同时还需要通过access_token去换取用户的pin才能最终访问到资源所有者的数据,因为数据库中的存储记录中是以pin的维度来存储的。交互通信如下图所示。
在这个阶段内除了上面说的换取访问令牌的通信,还有一种通信即刷新访问令牌请求通信。后面会介绍到。
2.3、资源服务和授权服务之间的通信
资源服务器和授权服务器之间通信的目的就是要通过access_token换取pin。实现这个目的可以让两个服务共享一个数据存储,也可以让授权服务器提供一个RPC接口供资源服务器来调用。交互通信如下图所示。
3、标准Oauth2下的第三方软件请求参数列表
3.1、获取CODE需要的请求参数
名称 |
是否必填 |
参数值 |
client_id |
是 |
第三方软件的平台唯一标识,相当于ID |
redirect_uri |
是 |
第三方软件的平台的秘钥,相当于密码 |
response_type |
是 |
code |
state |
否 |
一个随机值,要求发送和平台返回的值必须一致 |
注:state虽然不是必填参数,但是建议要有,它关乎跨站防护的安全问题,state的用法在后续关于Oauth2的安全文章中会重点介绍。
3.2、通过CODE获取ACCESSTOKEN的请求参数
名称 |
是否必填 |
参数值 |
client_id |
是 |
第三方软件的平台唯一标识,相当于ID |
client_secret |
是 |
第三方软件的平台的秘钥,相当于密码 |
grant_type |
是 |
authorization_code |
code |
是 |
code |
redirect_uri |
是 |
重定向URI,第三方软件的系统地址 |
4、标准Oauth2下的平台端响应参数列表
名称 |
说明 |
access_token |
访问令牌 |
token_type |
目前access_token的类型只支持bearer类型 |
expires_in |
access_token的过期时间 |
refresh_token |
用于重新获取access_token的值 |
如果access_token访问令牌过期了该怎么办,让用户再重新授权一次?这样的话体验会很差,access_token设置失效时间本身是为了安全性,有没有既能保证安全有不损害用户体验的方法,Oauth2.0提供了一种无须用户参与的情况下获取访问令牌的方法,就是refresh_token机制。比如用户购买了第三方软件时间周期为1年,那么在这1年之内,access_token会10天过期一次,这个时候就需要第三方软件利用refresh_token重新获取新的access_token来继续请求受保护的资源,这样则不需要用户重新授权,不然10天授权一次就是一个很糟糕的体验。
未完待续...
大话Oauth2.0(三)、非标准流程下的Oauth2组件及通信(未更新)
大话Oauth2.0(四)、Oauth2流程下的安全问题(未更新)
大话Oauth2.0(五)、Oauth2最佳实践(未更新)
END
往期文章:
点击文末 阅读原文 直接京东详情《架构修炼之道》
好看,就点一下在看^_^