OAuth Demystified for Mobile Application Developers
论文笔记 OAuth
作者:Eric Chen,Yutong Pei,Shuo Chen,Yuan Tian,Robert Kotcher,Patrick Tague
单位:Carnegie Mellon University,Microsoft Research
主要工作:
- 分析了OAuth协议的文档,并指出了对于开发者来说,哪些部分是可能存在理解错误或者没有说明到位的
- 研究了超过600个的APP来看开发者有没有能够成功实现授权和认证功能
OAuth简介
OAuth1.0 & OAuth1.0a

OAuth1.0流程与RP是绑定的,SP会对RP的请求进行签名验证。
上图所示为OAuth1.0a,其与OAuth1.0最大的区别在于verifier,这一参数防止了在OAuth1.0中可能发生的会话固定攻击。
OAuth2.0
OAuth共有4中模式,普遍使用的就以下2种

手机平台上的OAuth应用
授权
重点在于SP,因为受保护的资源在SP的服务器上
安全性保证:
- OAuth1.0
每一个对于token和受保护资源的请求都必须经过一个RP和SP之间的shared secret进行签名,以使SP知道这是来自RP的请求
- OAuth2.0的implicit grant
安全性主要依靠重定向URI来进行保证,这个重定向URL在RP注册到SP的时候就已经确定了,请求必须与其想匹配才能进行之后的步骤
- OAuth2.0的授权码模式
该模式下,安全性保证分为2个部分:
- APP ID和APP secret——以确定RP的身份
- Authorization code——以确定这和之前与其进行通信的是同一个用户
认证
重点在于RP,因为受保护的资源在RP的服务器上
RP必须保证:
- 从SP获得的user id不能被篡改
- 确认用来获得user id的OAuth token是被授予给自己的,而不是给其他的应用
三种OAuth协议作为认证时:
- OAuth1.0
安全,因为
- user id的交换是在服务器与服务器间完成的,所以不会被篡改
- 签名验证使得RP的前后一致可以得到保证
- OAuth2.0的implicit grant
不安全,因为OAuth2.0的access token不与RP绑定,所以无法确认用户是不是用这个access token来登录同一个RP
- OAuth2.0的授权码模式
安全。
尽管OAuth2.0与RP的不绑定使得其难以验证RP是否前后一致,但在授权码模式下,因为有了授权码,所以SP只需通过重定向URI返回授权码,使access token可以通过服务器间的API调用进行传递,从而让用户无法对其进行修改。同时,access token的获取则需要授权码,而授权码是与RP进行绑定的。
OAuth在移动端与网页端的区别
- 不同的重定向机制
- 网页端:使用状态码302
- iOS:custom scheme机制——利用custom scheme可以唤起相应的应用,但iOS允许多个应用可以对应同一个custom scheme
- Android:Intent机制
- 难以确定应用身份
- 网页端:通过DNS完成域名与网站实体的一一对应关系
- 但这在iOS和Android行不通
- 客户端的协议逻辑
- 网页端:重定向的请求会被直接送到服务器端,让服务器端进行处理
- 移动端:许多应用会首先在本地进行处理——但按照OAuth协议,用户的设备不应该背信任
现实问题
1. RP的secrets被存储于本地
即OAuth1.0中的consumer secrets,和OAuth2.0中的client secrets,这实际上指的是RP的secrets——这作为验证凭据之一不应该被存储到本地
2. 把授权过程当做认证
——可能来自于对于OAuth文档中“client authentication”一词的误解,这个指的是使用app id和app secret来对RP的身份进行验证,并不是指对用户的身份进行认证。
还有就是使用了implicit grant方式来进行认证——然而这一方式只能用于授权。
举例:
Facebook使用了经修改的implicit grant来进行第三方登录,它加入了一个appsecret_proof来进行安全性的加强,类似于将原本的过程与OAuth1.0的想法进行结合后的产物,为implicit grant的安全性提供了保证,如下图所示:

然而现实中,很少有RP真的实现了这一点,作者调查了72个使用了Facebook的RP,其中存在如下情况:
- 使用了常规的implicit grant(61个)
- 正确使用了appsecret_proof(10个)
- 错误使用了appsecret_proof(1个)
这是一个名为Keek的社交应用的OAuth流程,它将Facebook认证appsecret_proof的过程移交到了用户客户端,从而导致第6步的认证成功,可以进行implicit grant流程的请求可以被伪造。
除此之外,Google也与Facebook一样,存在同样的问题。
3. 重定向
(1)Custom scheme & Intent
- iOS
iOS利用Custom scheme来唤起另一个应用并传递access token的做法并不安全,因为custom scheme机制并不能验证发出请求的应用的身份。目前没有SP能够提供完全安全的服务。
- Android
在使用Intent时,保证安全的关键在于要对传回的值进行身份的认证。Facebook和Google的做到了这一点。当他们使用Intent将返回值传递给RP时,可以通过Android key hash来认证接收者的身份——这一点和检查重定向链接的作用相类似。
(2)Mobile Browser & WebView
- WebView
使用WebView几乎不可能完成安全的OAuth流程,因为通过WebView访问SP时,SP是无法确定RP的身份的。
4. 自定义的OAuth流程
腾讯在OAuth认证过程中加入了一个新的ID hash参数,这个参数是由RP的app id和用户的腾讯id加密后得到的,并把这个参数当做用户id使用,而不是使用access token去换得用户id。
他们也移去了用户授权的阶段,但这一行为引入了新的威胁——即在使用WebView时,一个恶意的应用可以伪装成一个正常应用来获得用户在使用这个正常应用时的id hash,而由于腾讯处理OAuth流程的网站对无论是网页还是客户端都是同一个,所以RP不得不使用WebView对此进行处理。
总结
- 要安全地传递access token,SP必须能够时刻识别出RP的身份。
- 对于授权来说,一个同意授权的对话框是必须的,包括授权给谁以及授权范围
- 对于认证来说
- RP不应该在本地存储或硬编码任何敏感数据、安全相关的协议逻辑
- RP必须假设攻击者可以篡改任何来自于用户设备的数据,所以得要保证用户想要用来认证的RP和最后获得用户id的RP是同一个