OAuth2.0学习笔记
什么是OAuth 2.0
1-第三方登录
2-服务授权
例如微信第三方应用要求用户微信授权:
例如百度地图、支付宝、豆瓣等第三方服务功能服务商提供的开发者平台里(以移动端为例),AppKey和SecretKey的使用,都是OAuth的使用。
3-基本概念明确
要了解OAuth的工作原理,首先必须明确几个概念:
RO(Resource Owner):资源所有者,对资源具有授权能力,例如用户
RS(REsource Server):资源服务器,它存储了用户的资源,并且拥有外部请求对资源的访问控制权限
Client :第三方应用,为了访问RS(资源服务器),它必须向RO(用户)获取取授权。这里为了支持开放授权功能以及更好地描述开放授权协议,oAuth引入了第四个参与的实体。
- AS(Access Server)授权服务器:它主要负责RO(用户)的身份验证,为RO提供授权批审的流程,并颁发授权令牌(Access Token)。
注意,为了便于协议描述,这里只是在逻辑上将AS与RS区分开,二者在实际当中的功能可以由同一台服务器来提供
综上,oAuth到底是为了解决什么问题才出现的呢?
OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准,即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权。
工作流程
整体示意图:
个人理解,在实际当中,过程应该在呈现方式上会有所变化(qq登录以****为例):
- 【第一步】:客户端请求用户授权。一般,用户在client选择授权动作,client将页面重定向至AS。
此时需要用户在这个页面授权验证,从用户层面来说,可以选择扫码、快捷、或者账号密码登录。或许有的小伙伴就有疑问了,不是说oAuth不需要用户提供用户名和密码吗?为什么这里又需要输入呢?
我的理解是,这里键入的账号密码是在服务商(即QQ提供的官方验证方式)而不是在client,oAuth解决的是client端的验证问题,client把授权请求提交给了服务商,那么后续的交互逻辑如何设计,那就是服务提供商(QQ)自己的事情了。当然,在这里QQ推荐的依然是扫码登录(毕竟账号密码还是存在钓鱼的风险)
【第二步】RO批准授权,并将“授权的证据”发送给客户端,至于RO如何批准(扫码?账号密码?),这是协议之外的事情,比较典型的做法是AS提供授权审批的界面,让RO(用户)显示批准。
【第三部】client拿着“授权的证据”和自己身份的凭证(通常就是AppKey),向AS请求“访问令牌(Access Token)”
- 【第四步】AS通过验证后,向client发送“访问令牌(Access token)”
- 【第五步】client携带者访问令牌去访问RS上之前授权过的(第1、2步)的资源。在令牌的有效期内,client可以多次去访问资源。
- 【第六步】RS验证令牌的有消息,比如是否伪造、是否越权、是否过期,验证通过后,才能提供服务。
对于用户来说,只有第一步和第六步是可见的,中间的过程都是client与AS、RS之间的交互。
可以看出在整个交互流程当中,第二部是关键,即用户如何才能给予客户端授权呢?下面来介绍一下客户端获取授权的四种模式
客户端的授权模式
客户端必须得到用户的授权(authorization grant),才能获得令牌(access token)。OAuth 2.0定义了四种授权方式。
- 授权码模式(authorization code)
- 简化模式(implicit)
- 密码模式(resource owner password credentials)
- 客户端模式(client credentials)
授权码模式
授权码模式是功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器与服务提供商的认证服务器互动。
(1) Client初始化协议的执行流程。首先通过HTTP 302来重定向RO用户代理到AS。Client在redirect_uri中应包含如下参数:client_id, scope (描述被访问的资源), redirect_uri (即Client的URI), state (用于抵制CSRF攻击). 此外,请求中还可以包含access_type和approval_prompt参数。当approval_prompt=force时,AS将提供交互页面,要求RO必须显式地批准(或拒绝)Client的此次请求。如果没有approval_prompt参数,则默认为RO批准此次请求。当access_type=offline时,AS将在颁发access_token时,同时还会颁发一个refresh_token。因为access_token的有效期较短(如3600秒),为了优化协议执行流程,offline方式将允许Client直接持refresh_token来换取一个新的access_token。
(2) AS认证RO身份,并提供页面供RO决定是否批准或拒绝Client的此次请求(当approval_prompt=force时)。
(3) 若请求被批准,AS使用步骤(1)中Client提供的redirect_uri重定向RO用户代理到Client。redirect_uri须包含authorization_code,以及步骤1中Client提供的state。若请求被拒绝,AS将通过redirect_uri返回相应的错误信息。
(4) Client拿authorization_code去访问AS以交换所需的access_token。Client请求信息中应包含用于认证Client身份所需的认证数据,以及上一步请求authorization_code时所用的redirect_uri。
(5) AS在收到authorization_code时需要验证Client的身份,并验证收到的redirect_uri与第3步请求authorization_code时所使用的redirect_uri相匹配。如果验证通过,AS将返回access_token,以及refresh_token(若access_type=offline)。
简化模式-密码模式-客户端模式
后面的几种模式,其实都是在授权码模式上面做的演变,只要理解了授权码模式,后面的这些模式就轻车熟路。
详细参见理解OAuth 2.0- 阮一峰
这里做一些摘录:
简化模式——client与AS交互的时候省去了AuthCode,直接可以在client中向验证服务器申请令牌,所有步骤都在浏览器中完成,令牌对访问者是可见的,且client不需要验证。比较适合使用的场景是用户资源不敏感,资源安全性要求较低时。
密码模式——就是在client当中使用用户名和密码向AS索要授权,然后向AS根据用户资料判断是否授权,在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分,或者由一个著名公司出品。而认证服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。
oAuth安全性分析
通过上面的一些介绍,我们再来看看关于oAuth的安全。在上面介绍的几种模式中,我们可以总结出如下的安全要素
(1)重定向的URL,如果发现请求中的重定向URL变法,则授权肯定失败
(2)authCode(授权码),即在http协议中并不会直接传输access token,而是会间接地去传输一个授权码
具体可以参考一篇非常优秀的博文: 帮你深入理解OAuth2.0协议的第四小节
服务商分析
【微信策略】
同豆瓣
【豆瓣策略】
通过AppKey构建认证请求,跳转至豆瓣的授权界面,用户授权后豆瓣返回accessToken,应用拿着accessToke去豆瓣获取相应的用户内容。
【百度策略】
网页js-使用AppKey,设置白名单。
在调用百度的api时,在请求的后面附上ak,然后结合白名单,就会判断此请求是否合法。