移动应用程序中的 OAuth 秘密

在使用 OAuth 协议时,需要从要委托给的服务获取一个秘密字符串。如果你是在一个网络应用程序中做这件事,你可以简单地将这个秘密存储在你的数据库或文件系统中,但是在一个移动应用程序(或者一个桌面应用程序)中处理它的最佳方式是什么呢?

在应用程序中存储字符串显然是不好的,因为有人可以很容易地找到它并滥用它。

另一种方法是将它存储在你的服务器上,并让应用程序在每次运行时获取它,而不是存储在手机上。这几乎同样糟糕,因为你必须在应用程序中包含 URL。

我能想到的唯一可行的解决方案是,首先像往常一样获得访问令牌(最好使用应用程序内部的 Web 视图) ,然后通过我们的服务器路由所有进一步的通信,这将附加到请求数据的秘密,并与提供商通信。不过话说回来,我是个安全新手,所以我真的很想听听一些知识渊博的人对此的看法。在我看来,大多数应用程序似乎并没有这么做来保证安全性(例如,Facebook Connect 似乎假设你在应用程序中将这个秘密放入了一个字符串中)。

另一件事: 我不认为最初请求访问令牌涉及到这个秘密,所以这可以在不涉及我们自己的服务器的情况下完成。我说的对吗?

37761 次浏览

是的,这是我们自己面临的 OAuth 设计的一个问题。我们选择通过自己的服务器代理所有呼叫。OAuth 在桌面应用程序方面并没有完全被淘汰。在不更改 OAuth 的情况下,我所发现的问题没有完美的解决方案。

如果你仔细想想,问我们为什么有秘密,主要是为了提供和禁用应用程序。如果我们的秘密泄露了,那么提供商只能撤销整个应用程序。因为我们不得不把我们的秘密嵌入桌面应用程序,我们有点搞砸了。

解决方案是为每个桌面应用程序设置不同的秘密。OAuth 并没有简化这个概念。一种方法是让用户自己创建一个秘密,然后自己把密钥输入到你的桌面应用程序中(一些 facebook 应用程序做了很长一段时间类似的事情,让用户自己创建 facebook 来设置他们的自定义测试和废话)。这对用户来说不是一个很好的体验。

我正在为 OAuth 的委托系统提出建议。这个概念是,使用我们自己的秘密密钥,我们从我们的提供商,我们可以发布我们自己的委托的秘密,我们自己的桌面客户端(每个桌面应用程序基本上) ,然后在认证过程中,我们发送这个密钥的顶级提供商回电话给我们,并与我们重新验证。这样我们就可以撤销发布给每个桌面客户端的自己的机密。(从 SSL 中借鉴了许多这方面的知识)。这整个系统将是最适合的增值网络服务,以及传递调用到第三方网络服务。

如果顶级提供程序提供了一个 API 来生成和撤销新的委托机密,那么这个过程也可以在没有委托验证回调的情况下完成。Facebook 正在做类似的事情,允许用户创建子应用程序。

网上有一些关于这个问题的讨论:

Http://blog.atebits.com/2009/02/fixing-oauth/ Http://groups.google.com/group/twitter-development-talk/browse_thread/thread/629b03475a3d78a1/de1071bf4b820c14#de1071bf4b820c14

Twitter 和 Yammer 的解决方案是一种身份验证别针解决方案: Https://dev.twitter.com/oauth/pin-based Https://www.yammer.com/api_oauth_security_addendum.html

正如其他人提到的,在设备上本地存储机密应该没有实际问题。

最重要的是,您总是可以依赖基于 UNIX 的 Android 安全模型: 只有您的应用程序可以访问您写入到文件系统的内容。只需将信息写入应用程序的默认 SharedPreferences 对象。

为了获得这个秘密,用户必须获得 Android 手机的 root 访问权限。

我对 OAuth 没有很多经验——但是每个请求不是都不仅需要用户的访问令牌,还需要应用程序使用者的密钥和机密吗?所以,即使有人偷了一个移动设备并试图从中获取数据,他们也需要一个应用程序密钥和秘密,才能真正做任何事情。

我一直认为 OAuth 背后的意图是让每个拥有 mashup 的 Tom、 Dick 和 Harry 都不必将您的 Twitter 凭证存储在空白处。我认为它很好地解决了这个问题,尽管它有局限性。而且,它的设计并没有考虑到 iPhone。

一种解决方案是将 OAuth 的秘密硬编码到代码中,而将 没有作为一个普通的字符串。以某种方式混淆它-把它分成段,移动字符的偏移量,旋转它-做任何或所有这些事情。黑客可以分析你的字节码并找到字符串,但是混淆代码可能很难找出。

这不是一个万无一失的解决方案,而是一个廉价的解决方案。

根据漏洞的价值,一些天才破解者可以不遗余力地找到你的密码。您需要权衡各种因素——前面提到的服务器端解决方案的成本、破解者花费更多精力寻找您的密码的动机,以及您可以实现的混淆的复杂性。

有些事情需要考虑一下。Google 提供了两种 OAuth 方法... 对于 web 应用程序,你可以注册域名并生成一个唯一的密钥; 对于安装的应用程序,你可以使用“匿名”密钥。

也许我在阅读过程中忽略了一些东西,但是看起来与一个已安装的应用程序分享你的 web 应用程序的唯一密钥可能比在官方安装的应用程序方法中使用“匿名”更安全。

Facebook 还没有实现严格意义上的 OAuth,但是他们已经实现了一种方法,让你不要把你的秘密嵌入到你的 iPhone 应用程序中: https://web.archive.org/web/20091223092924/http://wiki.developers.facebook.com/index.php/Session_Proxy

至于 OAuth,是的,我越想越觉得,我们有点吃撑了。也许 这个会修好它。

我同意费利西斯。OAuth 虽然优于 Basic Auth,但要成为一个好的移动应用程序解决方案还有很长的路要走。我一直在尝试使用 OAuth 对一个手机应用程序进行认证,使其成为一个 Google App Engine 应用程序。事实上,你不能可靠地管理移动设备上的消费者机密意味着默认是使用“匿名”访问。

Google App Engine OAuth 实现的浏览器授权步骤将您带到一个页面,其中包含以下文本: “站点 < some-site > 请求访问您的谷歌帐户以下列出的产品”

YourApp ( YourApp.appspot.com )-与谷歌无关

等等

它从回调 URL 中使用的域/主机名中获取 < some-site > ,如果您使用自定义方案拦截回调,那么您提供的回调 URL 可以是 Android 上的任何内容。 因此,如果你使用“匿名”访问或者你的消费者机密被泄露,那么任何人都可以编写一个消费者,愚弄用户,让他们访问你的邮件应用程序。

Google OAuth 授权页面也包含很多警告,根据您使用的是“匿名”、消费者机密还是公钥,这些警告的严重程度分为3个级别。

对于不懂技术的普通用户来说,这是相当可怕的东西。我不希望有一个很高的注册完成百分比与这种东西的方式。

这篇博文阐明了消费者机密是如何在已安装的应用程序中不起作用的。 Http://hueniverse.com/2009/02/should-twitter-discontinue-their-basic-auth-api/

我也在尝试为移动 OAuth 认证提供一个解决方案,通常在捆绑中存储秘密。

我突然想到一个疯狂的想法: 最简单的想法就是把秘密存储在二进制文件中,但是用某种方式混淆了,或者,换句话说,你存储了一个加密的秘密。所以,这意味着你必须存储一个密钥来解密你的秘密,这似乎花了我们整个循环。但是,为什么不使用一个已经在操作系统中的密钥,也就是说,它是由操作系统定义的,而不是由应用程序定义的。

所以,为了说明我的想法,你选择一个由操作系统定义的字符串,不管是哪一个。然后使用这个字符串作为密钥加密您的秘密,并将其存储在您的应用程序中。然后在运行时,使用密钥解密变量,这只是一个操作系统常量。任何黑客窥视你的二进制文件都会看到一个加密的字符串,但是没有密钥。

这样行吗?

使用 OAUth 2.0,您可以将秘密存储在服务器上。使用服务器获取一个访问令牌,然后移动到应用程序,您可以从应用程序直接调用资源。

对于 OAuth 1.0(Twitter) ,进行 API 调用需要保密。通过服务器代理调用是确保机密不受损害的唯一方法。

两者都需要一些机制,使服务器组件知道它是您的客户机调用它。这通常在安装时进行,并使用特定于平台的机制在对服务器的调用中获得某种类型的应用程序 ID。

(我是 OAuth 2.0规范的编辑)

使用 OAuth 2.0,您可以简单地使用客户端流来获取访问令牌,然后使用这个访问令牌来验证所有进一步的请求。那你就不需要什么秘密了。

在这里可以找到关于如何实现这一点的详细说明: https://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified#mobile-apps

不要将秘密存储在应用程序中。

您需要有一个服务器,应用程序可以通过 Https访问该服务器(很明显) ,并且您将这个秘密存储在该服务器上。

当有人想通过您的移动/桌面应用程序登录时,您的应用程序只需将请求转发给服务器,然后服务器将附加秘密并将其发送给服务提供商。然后,服务器可以告诉应用程序它是否成功。

然后,如果你需要从服务中获得任何敏感信息(facebook,google,twitter 等) ,应用程序会询问你的服务器,你的服务器只有在它正确连接的情况下才会提供给应用程序。

除了将它存储在服务器上,实际上没有其他选择。客户端没有什么是安全的。

注意

也就是说,这将只保护您免受恶意客户端,但不客户端针对恶意您和客户端针对其他恶意客户端(钓鱼) ..。

OAuth 在浏览器中比在桌面/移动设备上要好得多。

授权代码授予类型有一个名为 代码交换证明密钥(PKCE)的新扩展。有了它,你就不需要客户的秘密了。

PKCE (RFC7636)是一种保护不使用 客户的秘密。

它主要被本地和移动应用程序使用,但是这项技术可以 也适用于任何公共客户。它需要额外的 由授权服务器支持,因此它只在 某些供应商。

https://oauth.net/2/pkce/

有关详细信息,可以阅读完整的 RFC 7636这个简短的介绍

所有这些解决方案都不能阻止一个坚定的黑客嗅探从他们的移动设备(或模拟器)发送的数据包,以查看 http 头中的客户机机密。

一个解决方案可能是有一个动态的秘密,它是由一个时间戳加密的私有双向加密密钥和算法。然后服务解密该秘密并确定时间戳是否为 +/-5分钟。

这样,即使秘密泄露,黑客也只能使用最多5分钟。