我需要在iOS和Android原生应用程序中集成OAuth2。我一直在研究OAuth 2.0和移动应用程序,并找到了这个文档-谷歌api -使用OAuth 2.0安装应用程序
上面的文档基本上详细说明了如何在移动应用程序中使用google OAuth 2.0端点。
文件内容如下-
- 注册应用程序时,指定该应用程序是已安装的应用程序。这会导致redirect_uri参数的不同值。
- 注册过程中获得的client_id和client_secret嵌入到应用程序的源代码中。在此上下文中,client_secret显然不被视为秘密。
- 授权码可以通过浏览器的标题栏返回给您的应用程序,也可以通过查询字符串返回给
http://localhost
端口。
假设用户的智能手机上安装了两个应用程序。
App1 -使用Google OAuth2.0端点的合法应用
App2 -恶意应用
我真的不确定的是,上述在原生移动应用程序中集成/消费OAuth2.0端点的技术是否不安全,或者我错过了什么。这是我的问题-
- redirect_uri可以是
http://localhost
URL,可以包含任意端口号。端口号不是初始API配置的一部分,因此它可以是任何有效的端口号。此外,client_id(不应该是一个秘密)和client_secret并不是真正的秘密,因为它们嵌入在移动应用程序的源代码。
使用上面的条件,下面是不是有可能-
- 用户启动App2
- App2将用户重定向到Google OAuth2.0端点,然而在请求中,App2包含App1的client_id,并包含App2正在侦听的本地端口号。
- 当用户被重定向并验证到Google OAuth2.0端点时,Google会向用户指示"App1(合法应用)正在代表用户请求访问Google API/数据",这看起来像是网络钓鱼攻击,因为用户可能会认为是App1请求访问。
- Google OAuth2.0将向App2发出授权码,然后App2可以发出下一个请求,包括App1的client_id和client_secret,并获得access_token和refresh_token,并继续从Google访问用户数据。
- redirect_uri也可以是- urn:ietf:wg:oauth:2.0:oob,意思是-
该值向Google Authorization Server发出信号,表明应该在浏览器的标题栏中返回授权码。当客户机在没有重要的客户机配置的情况下无法侦听HTTP端口时,这很有用。Windows应用程序具有这个特性。
当使用这个值时,应用程序可以感觉到页面已经加载,并且HTML页面的标题包含授权代码。然后,如果您希望确保用户永远不会看到包含授权码的页面,则由应用程序决定是否关闭浏览器窗口。执行此操作的机制因平台而异。
上面表示在浏览器窗口的标题中返回授权码。
我的问题是- App2也可以感觉到页面已经加载并捕获授权码,然后使用它(在App1之前)与client_id和client_secret一起获得access_token和refresh_token。浏览器实例是全局的,任何应用程序都可以监控它,上面的攻击场景是有效的,或者浏览器实例是特定于应用程序的,所以只有App1可以感知/监控更改?
我的理解是正确的还是我错过了什么?我是否遗漏了任何缓解上述威胁的缓解措施?或者上述风险是否有效,但考虑到我们是在移动操作系统平台上?
在移动应用中使用OAuth2.0的安全方式是什么?—在浏览器页面中显示授权码,由用户在应用程序中手动输入授权码?在这种情况下,浏览器实例是私有的,这样其他应用程序就无法监视它并在用户将其输入合法应用程序之前获得授权码本身吗?
感谢您的帮助
Thanks and Regards
根据我的经验,我发现很少有库真正支持以一种干净的方式检索授权代码。
在大多数移动平台上,你可以"监听"重定向url (http或一些自定义方案)
例如,在Android上,可以很容易地创建一个活动来检索访问令牌(基于通过重定向URL接收的授权代码)。
<activity android:name=".OAuthAccessTokenActivity" android:launchMode="singleTask">>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" android:host="localhost" />
</intent-filter>
</activity>
在本例中
http://localhost
在Android这样的移动平台上,这似乎是一件合乎逻辑的事情。
同样可以在iOS上完成,但如果我没记错的话,iOS的Google OAuth库使用页面标题方法。
从技术上讲,这两种流之间没有区别。唯一的区别是重定向URL的语法,导致授权代码的位置不同。
从安全的角度来看,没有OAuth2客户端秘密,单独的授权代码是没有价值的。
让用户输入授权码是我不习惯在Oauth2流中看到的东西,但这是可能的。我怀疑它会增加任何安全明智的东西。恕我直言,这只会让用户感到沮丧。
这并不意味着检索和处理授权代码有不同的方法(通过使用本地主机或自定义URI方案重定向自动捕获代码,或手动交付)
不是对这个问题的直接回答,但对于像我这样来到这里并得到过期回复的人来说。最好从这里开始:Google已经发布了他们的OAuth Java库,而Scribe已经为Java做好了准备。