前言
这篇文章前前后后写了两个多礼拜,也是自己第三次写4000字以上的技术单篇文章。写作过程先是根据自己的思考和资料查找确认,再结合宙斯开放平台的实际使用,每天中午吃过饭一个小时来将这些内容碎片化的记录下来,今天得以利用整块的时间梳理总结完成。
研究Oauth这个方向的原因,第一是我本身就在做开放平台相关的工作,我需要对这一技术有个更深的了解;第二是今年618值班期间对线上开放安全的谨慎心理促使我去上 查找有关Oauth安全使用。
当时发现了一本正在预售的《Oauth2实战》这本书,心想关于Oauth的技术居然也有人写成了一本书,那时候第一反应是,只要有了方向就有了厚度。这也更加坚定了我深入研究这种技术的信心。
正文开始
Oauth的历史起源
回顾历史,在2007年以前所有的WEB服务公司,包括现在我们已经知名的Twitter和Google等互联 巨头企业,这些大的互联 公司都有很多个系统,如果用户需要在这些系统之间无缝浏览,大部分都是通过一种叫做分布式认证OpenID的方式来实现。再进一步如果他们要想让第三方应用访问自己的API都是利用各自的专有实现,因为OpenID的方式只是一种认证,解决了“是不是”的问题,它无法将用户名和密码用于API来解决“可不可以”的问题。
为了解决这个问题,当时一些开发人员尝试发明一种协议,可以允许用户对API访问授权。期望的是让第三方应用只要获得用户的授权并得的一个访问令牌,就能使用这个令牌来访问API。在2007年12月Oauth Core 1.0发布,象所有的新生事物一样,Oauth1.0也有它不完善的地方,其中就包括被发现会话固化攻击的漏洞,直到2009年6月发布了Oauth Core 1.0 Revision A版本彻底解决了这一问题。
在紧接着的2010年5月互联 工程任务组(IETF)发布了Oauth 2.0的草案。在2012年IETF最终批准了Oauth 2.0 核心规范,我们现在所有使用的Oauth技术都是基于这一规范。Oauth2.0对比Oauth1.0最大的区别,除了安全性进一步提高之外,还有一个重要本质区别,Oauth2.0是在基础层面提供了设计规范,也就是说我们只要遵守了这种规范就可以灵活地应用到我们现实世界的各种场景。
现在Oauth2.0早已经是互联 上首选的授权协议,无论大型互联 企业还是初创型企业,都在广泛的使用这一协议。
最标准的Oauth2流程
Oauth的最原始背景就是解决WEB应用下的授权的安全问题,因此一定不能缺少浏览器的参与。对于非标准条件下的Oauth流程在后续的文字中我们会有讲述,那个时候可能有的场景是不需要浏览器的。现在我们在叙述的是标准场景下的Oauth使用。
Oauth组件间的通信包括前端通信和后端通信,前端通信就是组件之间的需要交互的信息数据在浏览器里面流转,后端通信就是组件之间需要交互的数据信息通过WEB SERVER之间流转。实际上只有标准场景下的Oauth2流程才会既使用前端通信又使用后端通信,这点在介绍非标准场景下的Oauth使用的时候也会去分析,大家先记下来。
资源所有者A要授权正在使用的第三方软件来能够访问A在平台上受保护的资源,那么A通过浏览器首先访问的是第三方软件的URI地址,此时第三方软件遵循Oauth2.0的协议并按照平台的要求拼接授权URL,将用户引导到平台的授权页面,这个时候发生了第一次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的获取变得更安全了。
以上交互通信如下图所示。
2-微信小程序
那么微信小程序采取的授权流程又是怎样的呢,我们到微信小程序官方文档上去搜索会发现,微信的规范是要求开发者采用客户端凭据的方式来获取调用后台接口的凭据ACCESS_TOKEN。如下截图所示,
微信小程序的授权方式实际上是Oauth2.0多种授权方式的其中一种,叫做客户端凭据方式。从请求参数中的授权类型这个参数可以看到grant_type的值为client_credential。这种授权方式就没有了授权码CODE或者其它任何换取TOKEN的临时凭据。
向授权服务器进行身份认证的请求参数是appid和secret,一个是应用的ID,一个是应用被分配的秘钥。同时客户端凭据这种授权方式中也不会有刷新令牌,因为授权系统会认为客户端可以随时获取新令牌。
不过需要注意的一点是,微信小程序也有个授权,根据微信官方文档可以得知wx.authorize(Object object)这个授权并没有返回我们熟知的Oauth里面的CODE等兑换TOKEN的凭据。
实际上这个授权是让第三方小程序能够获取到微信APP里面的功能以及手机本身的功能,比如拍照、录音等。如果是需要发起HTTP请求调用的API是需要通过上文说的客户端凭据的方式。
但微信给我们返回的数据都是加密的,解密的时候需要我们登录的时候的SESSION_KEY来作为秘钥解密,当然每个登录用户的SESSION_KEY是不一致的。
Oauth面临的安全风险
在Oauth的发展历史上,最大的”安全风险漏洞”事件,可能是2014年被新加坡的一位大学学生发现的了,据记载当时可谓影响了全世界的互联 公司,腾讯、阿里巴巴、支付宝、搜狐、 易、人人 、开心 、亚马逊、微软、eBay、Facebook、Google、雅虎等等这些巨头们都受到波及。但后续证明这个当时被称为”隐蔽重定向漏洞”,并不是Oauth本身的漏洞。
实际上Oauth的使用方没有按照Oauth的标准去接入,涉及到的上述公司均反馈是出现在他们平台上的第三方系统,而不是公司的自有站点。这也就是刚开始我们描述安全风险漏洞的时候为什么加了引 ,我们说那一次引起轰动的”漏洞”是没有按照标准接入的原因正是忽略了回调URL校验。
我们来看下发生这个问题点的位置,如下图所示。在黑色圈里面的回调URL是开发者在入住开放平台的时候填写的,如果授权码流程的第一个重定向被恶意用户篡改了callback的值,授权服务器又没有跟注册时候入库的值做校验,在第二次重定向的时候就会把数据发送到了恶意用户所指定的服务器上面去了。
应对策略就是在第三方应用请求code的url上增加state参数,并把state的参数值保存起来,授权服务器发起重定向请求的时候再把state参数值带过来,第三方应用会做一个state值比对判断,如果两个state的值不相同,则有可能发生了被伪造攻击。
关于Oauth的安全上面只是列举了其中一个方面,自从Oauth1.0升级到Oauth2.0之后,Oauth实际上从单体的变成了模块化,比如有客户端(第三方应用)、授权服务器、受保护资源,这三个模块每一个都面临着因使用Oauth规范不当而出现的安全风险问题。
总结
开放平台的基础技术需要 “两条腿” 能够跑起来,这两条腿分别是 关和Oauth。 关可以让内部的API被外部调用,Oauth可以保护这些被调用的API。Oauth是一种协议,也是一种工具。Oauth本身是属于安全范畴的,它管理者API的访问权限,守护者重要的数据。
reference
https://docs.alipay.com/mini/introduce/authcode 支付宝小程序授权
https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/access-token/auth.getAccessToken.html 微信小程序授权
推荐阅读:
自学架构设计你总结了 4 个方法
记录一次系统性能调优过程
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!