OAuth 2.0中的客户端秘钥

104

要使用谷歌云端硬盘API,我必须使用OAuth2.0进行身份验证。对此我有几个问题。

  1. 客户端ID和客户端密钥用于识别我的应用程序。但如果它是客户端应用程序,则必须将它们硬编码。因此,任何人都可以从源代码中反编译并提取它们。这是否意味着一个不良应用程序可以通过使用好的应用程序的客户端ID和密钥来冒充好的应用程序? 因此,当实际上是由不良应用程序请求时,用户会显示一个请求授权许可的屏幕,以便授予好的应用程序的权限?如果是,我该怎么办?还是说我其实不需要担心这个问题?

  2. 在移动应用程序中,我们可以嵌入一个Webview到我们的应用程序中。由于请求权限的应用程序实际上是一个“浏览器”,所以很容易从Webview中提取密码字段。 因此,在移动应用程序中使用OAuth不具有客户端应用程序无法访问服务提供商的用户凭据的好处吗?


2
我猜当应用程序要求用户提供他们的Facebook、Twitter、Dropbox或其他凭据时,人们通常会感到怀疑。我怀疑很少有普通人会阅读OAuth规范并说“现在我很安全”,而是运用常识,一般不使用他们不信任的应用程序。 - Igor Čordaš
真的是一个很棒的问题,绝对应该有更多的分数。 - Shravan
你可以在第一次成功登录时从服务器下载ClientId和secret,并将其保存在钥匙串中,就这样。 - Shravan
@Sharvan 我可能错了,但我认为在已经取得 root 权限的手机上,钥匙串是容易受到攻击的,因此你的客户端密钥可能会被公开。 - chichilatte
3个回答

22

我曾经和这里的问题1一样,最近自己进行了一些研究,我的结论是不保密"客户端密钥"也没关系。 在OAuth2规范中,不保守客户机密性的类型被称为"公共客户端"。 以下事实可以防止恶意人员获取授权码,然后访问令牌。

1. 客户端需要直接从用户那里获取授权码,而不是从服务中获取

即使用户表示信任客户端,客户端也不能通过显示客户端ID和客户端密码从服务中获取授权码。 相反,客户端必须直接从用户那里获取授权码。(通常通过URL重定向完成,稍后会谈到。) 因此,对于恶意客户端来说,仅知道用户信任的客户端ID/密码是不够的。它必须以某种方式涉及或欺骗用户,以便获得授权码, 这应该比仅知道客户端ID /密码更难。

2. 重定向URL已使用客户端ID/密码注册

假设恶意客户端以某种方式成功地涉及了用户,并使其点击服务页面上的"授权此应用"按钮。 这将触发服务响应URL重定向响应,其中包含授权码。 然后,授权码将从用户的浏览器发送到重定向URL,并且客户端应在重定向URL上侦听以接收授权码。 (重定向URL也可以是localhost,我发现这是"公共客户端"接收授权码的典型方式。) 由于此重定向URL已使用客户端ID/密码在服务中注册,恶意客户端没有办法控制授权码的提供位置。 这意味着具有您的客户端ID/密码的恶意客户端有另一个障碍来获取用户的授权码。


3
很有前途,你有相关的参考资料吗?如果有的话会让人更有信心。 - gauteh
1
我在Drive文档中看到,在已安装的应用程序中,客户端密钥并不是真正的秘密,但他们没有解释为什么可以在那里存储它。你的解释帮了很多忙! - Martin Spasov

17

我本来想针对您的问题写评论,但结果发现要说的话太多了,所以在答案中表达我的观点。

  1. 是的,这是一个真正的可能性,并且基于此有一些漏洞。建议不要将令牌保密保存在你的应用程序中,在规范中甚至有一部分明确指出分布式应用程序不应该使用这个令牌。现在你可能会问,但 XYZ 要求使用它才能正常工作。在这种情况下,他们没有正确实施规范,你应该 A 不使用该服务(不太可能),或者 B 尝试使用一些混淆方法来保护令牌使其更难被找到或被滥用为代理服务器。

    例如,Facebook 安卓库中存在一些错误,导致它泄漏令牌到日志中,你可以在这里找到更多信息: http://attack-secure.com/all-your-facebook-access-tokens-are-belong-to-us 和这里:https://www.youtube.com/watch?v=twyL7Uxe6sk。 总之,对第三方库的使用要格外小心(这其实是常识,但如果令牌劫持是您最担心的问题,请再加一份谨慎)。

  2. 我已经抱怨第二点很长一段时间了。我甚至在我的应用程序中做了一些变通措施,以修改同意页面(例如更改缩放比例和设计以适合应用程序),但没有任何阻止我从读取 Web 视图内的用户名和密码字段值。因此,我完全同意您的第二点,并认为它是OAuth规范中的一个重大“漏洞”。关键是,在规范中,“应用程序无法访问用户凭据”只是一个梦想,给用户错误的安全感...而且我想人们通常会对要求他们提供 Facebook、Twitter、Dropbox 或其他凭据的应用程序产生怀疑。我怀疑许多普通人并不会阅读 OAuth 规范,并说“现在我安全了”,而是运用常识,普遍不使用他们不信任的应用程序。


4
即使您在SSL隧道中发布客户端ID和客户端密码,它们也不会安全。是的,它们比受到中间人攻击更安全。如果用户代理您的HTTPS呼叫,则可以接受错误证书并查看您发布的所有内容。顺便说一下,这是移动设备上窃取某人客户端密码的最简单方法。 - EpicThreeDev
6
我感谢您的评论,但无法将其与我的答案联系起来... 您能否详细说明为什么要评论我的答案?因为我明确指出在分布式应用程序中不应使用客户端密钥,另一点是即使使用OAuth,在应用程序中也有获取用户凭据的解决方法,因此用户应该信任应用程序提供者而不是OAuth。 - Igor Čordaš
我不理解您所说的“如果用户代理您的HTTPS调用”的意思。是的,用户可以获得使用HTTPs发送的数据,并且可以自由地代理调用。据我所知,您建议这是一个相当好的替代方法,以避免分解apk以获取秘密,但是您一开始就不应该发送应用程序秘密。 - Igor Čordaš
那么对于第一点,有问题的应用程序需要访问相同的系统并从“同一”设备检索访问/刷新令牌吗? - gauteh
在这种情况下,您认为“同一系统”是什么并不清楚。应用程序创建一个Webview,在其中显示确认页面,并可以访问该视图中的所有数据(包括托管访问令牌的cookie或url参数)。在某些情况下,跨应用程序访问也是可能的,例如,如果一个应用程序可以访问其他应用程序的日志,则可以在那里找到令牌,如使用fb lib bug时所述。 - Igor Čordaš

1

1
至少在我提出请求三年后,它终于被“修复”了 :) - Bear

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接