移动应用中的OAuth机密


137

使用OAuth协议时,您需要从要委派给该服务的秘密字符串。如果您是在Web应用程序中执行此操作,则可以仅将秘密存储在数据库或文件系统中,但是在移动应用程序(或与此相关的桌面应用程序)中处理秘密的最佳方法是什么?

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

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

我能想到的唯一可行的解​​决方案是,首先正常获取访问令牌(最好使用应用程序内部的Web视图),然后将所有进一步的通信路由到我们的服务器,这会将秘密添加到请求数据中并进行通信。与提供者。再说一次,我是安全菜鸟,所以我真的很想听听一些知识渊博的人们对此的看法。在我看来,大多数应用程序都不会采用这些长度来保证安全性(例如,Facebook Connect似乎假定您将秘密信息直接放入应用程序中的字符串中)。

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


抱歉,如果我不明白,但是将代码存储在应用程序的数据库中怎么了?由于这些令牌是在用户验证其帐户之后生成并存储的,因此应该安全地假定该用户希望移动设备存储访问权限。

即使在用户授权您访问其帐户之后(例如在Twitter上),您也必须使用从尝试访问的服务中获取的机密。在与服务器进行的所有通信中,将使用此机密以及身份验证密钥和其他一些密钥。因此,可以,您可以存储访问密钥,但不应存储该秘密,因为它可以与任何身份验证密钥一起使用以滥用服务。再次,我很高兴被对此了解更多的人予以纠正。
Felixyz

1
OAuth提供了一种身份验证方法,可以保护原始用户的登录数据。为了使之成为可能,将生成一个新的唯一登录组合,该组合仅与唯一应用程序的按键组合一起使用。与存储用户的登录数据相比,最大的好处是,首次授权,这些数据是完全安全的,在任何违反情况下,用户都可以简单地撤消授权的访问权限。当然,不保存机密也没有意义,因为用户随后需要重新进行身份验证(这不是用户授予应用程序访问权限时所希望的)。

@poke应该保存用户与提供者批准您的应用时获得的身份验证密钥,但不应保存在发布应用之前从提供者那里收到的秘密令牌(对于台式机或移动应用;如果是一个Web应用程序,您显然可以将密钥存储在服务器上,如问题所述)。
Felixyz

4
据我对oAuth的理解-在桌面应用程序的情况下,使用诸如ieinspector.com/httpanalyzer/index.html之类的工具非常容易嗅探/监视HTTP / HTTPS流量, 因此可以很容易地找到您的令牌和令牌秘密容易。因此,唯一的保护就是您的消费者秘密。现在,如果您在应用程序内存储了秘密并且有人能够找到它,那么将其他任何应用程序模拟为您的应用程序就成了孩子的玩法。如果我错了,请纠正我。
Varun

Answers:


38

是的,这是我们面临的OAuth设计问题。我们选择通过自己的服务器代理所有呼叫。对于桌面应用程序,OAuth并未完全被淘汰。如果不更改OAuth,就找不到完美的解决方案。

如果您考虑一下并提出问题,为什么我们会有秘密,这主要是用于提供和禁用应用程序。如果我们的秘密被泄露,那么提供商只能真正撤消整个应用程序。由于我们必须在台式机应用程序中嵌入秘密,因此我们有点困惑。

解决方案是为每个桌面应用程序设置不同的秘密。OAuth并没有使这个概念变得容易。一种方法是让用户自行创建一个秘密,然后自行将密钥输入到桌面应用程序中(某些facebook应用程序做了很长时间的相似操作,让用户自行创建facebook来设置自定义测验,然后废话)。对于用户而言,这不是很好的体验。

我正在为OAuth委派系统的提案。概念是,使用从提供商那里获得的我们自己的密钥,我们可以将自己的委托密钥发布给我们自己的桌面客户端(基本上每个桌面应用程序一个),然后在身份验证过程中,将该密钥发送到顶层提供者,它会回电话给我们并与我们重新验证。这样,我们就可以撤销发布给每个桌面客户端的秘密。(从SSL借用了很多方法)。整个系统对于增值Web服务以及将呼叫传递到第三方Web服务都是完美的。

如果顶级提供程序提供了用于生成和撤消新的委托机密的API,则也可以在没有委托验证回调的情况下完成此过程。Facebook通过允许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


这很有意思,尽管它证实了我的担心,但OAuth对于台式机/移动应用程序并不是很好。当然,攻击者必须首先获取机密,然后再嗅探某人的凭据,因此需要相当大的决心。对于台式机,该引脚解决方案是可行的,但对于移动imo来说,该解决方案比较适合。
Felixyz

由于此问题不适用于您的方案,因此您提出的方案将如何帮助增值Web服务?另外,我看不到它将如何与提供新机密的提供程序一起使用,因为您甚至需要一个“主机密”来请求这些新机密,因此您至少需要一个调用您自己的服务器(该服务器拥有主要秘密)。但这当然比通过您自己的服务器路由所有流量更好。澄清最欢迎!并随着提案的进展在这里更新!
Felixyz

5
只是好奇:您如何确定呼叫代理服务器的事情是合法的?
davidtbernal 2011年

1
对notJim的回应:允许您泄露消费者机密的主要风险是,可以使用它开发恶意(或愚蠢)应用程序,这会损害您的声誉,并增加因API滥用/滥用而关闭合法应用程序的风险。通过代理您控制的Web应用程序代理所有需要您的秘密的呼叫,您可以回到监视滥用模式的状态,并在您要使用的API决定关闭之前,在用户或访问令牌级别撤消访问降低您的整个服务水平。
quasistoic,2012年

我同意这里的观点,您将需要使用启用SSL的浏览器来处理oauth调用。出于某些原因,这是一件好事,其中包括将来轻松管理任何安全更新,并且实际应用程序中的任何内容都不需要随时间更新。Zac指出Twitter提出了PIN解决方案,我实际上也考虑过,因为您不能信任该应用程序来安全地获取代码。我建议使用带有现代加密功能的“ Nonce”以及PIN和密码来通过Web服务器代理请求。
标记

18

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

使用OAuth 1.0(Twitter),进行API调用需要密码。通过服务器代理呼叫是确保机密不被泄露的唯一方法。

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

(我是OAuth 2.0规范的编辑)


2
您能否详细说明“特定于平台的机制以获取某种应用程序ID”?服务器组件如何验证客户端身份?我认为可以通过客户端配置来完成。例如,为每个客户端部署一个新的唯一SSL证书。你是这个意思吗?如果比这更复杂,也许您可​​以参考更深入的文章?
Cheeso 2014年

2
我记得一些安全人员在谈论如何做到这一点。有一个对操作系统的调用,该调用返回了签名的令牌,然后您可以将其发送到服务器并进行验证。抱歉,我没有具体信息。这是一个错误,可以使用一些很好的例子。
迪克·哈特,2015年

2
@DickHardt,但是在此场景中,您如何确保移动应用程序确实是您的应用程序,而不是欺诈性应用程序?
拉斐尔·梅布雷夫斯

11

一种解决方案是将OAuth密码硬编码到代码中,而不是将其作为纯字符串。以某种方式进行模糊处理-将其拆分为段,按偏移量移动字符,旋转它-执行任何或所有这些操作。破解者可以分析您的字节码并找到字符串,但是混淆代码可能很难弄清楚。

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

根据漏洞利用的价值,某些天才破解者可能会花更长时间寻找您的秘密代码。您需要权衡以下因素:先前提到的服务器端解决方案的成本,鼓励破解者花费更多精力查找秘密代码的动机以及可以实现的混淆的复杂性。


1
是的,我认为这是合理的。某人首先要提取消费者的秘密,然后再窃取人们的凭据以进行某种手段,这需要大量的决心。对于高知名度的应用程序,我不确定这是否足够,但是对于一般的应用程序,我认为您必须平衡实现时间与较小的安全威胁,这是正确的。
Felixyz

7
只需要一个用户付出努力,然后发布或分享您的秘密。一旦揭露了秘密,您的服务就可能因滥用行为激增而彻底关闭,这完全不受您控制。
quasistoic,2012年

8
混淆根本不是安全的。这比没有安全要糟糕得多,因为它给开发人员一种错误的安全感。zh.wikipedia.org/wiki/Security_through_obscurity
Paul Legato

8
“模糊处理根本不是安全性。这比根本没有安全性还差,因为它给开发人员一种错误的安全感。” 废话。没有人说混淆可以带来良好的安全性。但是,如果我要通过我的apk分发OAuth机密,那么混淆总比没有好。Google还建议在应用内存储密钥/秘密时进行混淆处理。如果没有其他措施,这些措施可以阻止随意的黑客,这总比没有好。像您这样的笼统声明将不完善的安全等同于没有安全。那根本不是真的。不完美就是不完美。
hungryghost 2015年

1
混淆无济于事,因为无论您进行多少移位或编码,您都仍将一起构造密钥并使用该密钥来构建您的API请求。动态地将API挂在正确的位置相当简单,以在HTTPS加密之前转储您正在发送的请求。因此,请不要在您的应用程序中嵌入秘密密钥,除非确实没有其他选择。
C0deH4cker

6

不要将机密存储在应用程序内部。

您需要有一个可以由应用程序通过https(显然)访问的服务器,并将机密存储在该服务器上。

当某人想要通过您的移动/桌面应用程序登录时,您的应用程序将简单地将请求转发到服务器,服务器将附加该机密并将其发送给服务提供商。然后,您的服务器可以告诉您的应用程序是否成功。

然后,如果您需要从服务(facebook,google,twitter等)中获取任何敏感信息,则应用程序会询问您的服务器,并且只有在正确连接后,服务器才会将其提供给应用程序。

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

注意

就是说,这只会保护您免受恶意客户端的侵害,而不会保护客户端免受恶意您的侵害,而不保护客户端免受其他恶意客户端的侵害(网络钓鱼)...

OAuth是浏览器中比台式机/移动设备更好的协议。


1
这不是让黑客的生活更轻松吗?!因为现在,从技术上讲,为了访问服务器资源,我们需要客户端ID,因为服务器无论如何都会将机密附加到请求中。我错过了什么吗?
Hudi Ilfeld

@HudiIlfeld是的,您缺少某些内容:客户端需要登录到服务器。只要他没有登录,服务器就不会返回任何信息。一种管理方式是,在首次发送凭据后,服务器将访问令牌返回给客户端,然后客户端随以后的每个请求发送此访问令牌。这里有很多选择。
Gudradain

4

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

PKCE(RFC 7636)是一种保护不使用客户端机密的公共客户端的技术。

它主要由本机和移动应用程序使用,但是该技术也可以应用于任何公共客户端。它需要授权服务器的额外支持,因此仅在某些提供程序上受支持。

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

有关更多信息,您可以阅读完整的RFC 7636此简短介绍


2

这是要考虑的事情。Google为网络应用程序提供了两种OAuth ...方法,用于注册域并生成唯一密钥的Web应用程序,以及用于使用密钥“匿名”的已安装应用程序的OAuth...。

也许我在阅读中有所遗漏,但是似乎与在已安装的应用程序中共享Web应用程序的唯一密钥相比在正式安装的应用程序方法中使用“匿名”更为安全。


2

使用OAuth 2.0,您可以简单地使用客户端流程获取访问令牌,然后使用该访问令牌对所有其他请求进行身份验证。然后,您根本不需要任何秘密。

有关如何实现此功能的详细说明,请参见:https//aaronparecki.com/articles/2012/07/29/1/oauth2-simplified#mobile-apps


提供的服务支持“客户端流”。许多人不需要,而是需要客户端ID和客户端机密才能获得此访问令牌。
Damian Yerrick '16

0

我没有大量的OAuth经验-但是不是每个请求都不仅需要用户的访问令牌,还需要应用程序使用者密钥和机密吗?因此,即使有人窃取了移动设备并试图从中提取数据,他们也将需要应用程序密钥和机密才能真正执行任何操作。

我一直以为OAuth的目的是使每个具有混搭功能的Tom,Dick和Harry不必将您的Twitter凭据存储在明文中。我认为尽管有其局限性,它仍然可以很好地解决该问题。此外,它并不是真正为iPhone设计的。


没错,OAuth的设计主要考虑了Web应用程序,我相信它可以很好地实现这一目标。是的,您需要消费者令牌和密钥来签署每个请求,而问题在于密钥的存储位置。如果有人窃取了访问密钥,这并不重要,因为它可以被撤销,但是如果有人获取了消费者密钥,则您应用程序的每个副本都会受到损害。
Felixyz

OAuth 1需要签署每个请求。OAuth 2仅需要访问令牌。获取令牌时,都需要密钥和机密。
迪克·哈特,2015年

0

我同意Felixyz。OAuth虽然比Basic Auth更好,但要成为移动应用程序的良好解决方案还有很长的路要走。我一直在使用OAuth验证手机应用程序到Google App Engine应用程序的身份。您无法可靠地管理移动设备上的消费者机密这一事实意味着默认设置是使用“匿名”访问。

Google App Engine OAuth实施的浏览器授权步骤将带您进入一个包含以下文本的页面:“网站<some-site>正在请求访问以下所列产品的Google帐户”

YourApp(yourapp.appspot.com)-与Google无关

等等

它使用您提供的回调URL中使用的域名/主机名中的<some-site>,如果您使用自定义方案来拦截回调,则在Android上可以是任何名称。因此,如果您使用“匿名”访问方式或您的消费者秘密被盗用,那么任何人都可以编写一个消费者来欺骗用户,让其无法访问您的gae应用。

Google OAuth授权页面上也确实包含许多警告,警告的严重性分为3级,具体取决于您使用的是“匿名”,消费者秘密还是公共密钥。

对于技术上不精通的普通用户而言,这是非常可怕的东西。我不希望这种方式的注册完成率很高。

这篇博客文章阐明了消费者机密在安装的应用程序中如何真正发挥作用。 http://hueniverse.com/2009/02/should-twitter-discontinue-their-basic-auth-api/


0

我还试图提出一种用于移动OAuth身份验证的解决方案,并通常在应用程序捆绑包中存储机密信息。

一个疯狂的主意打了我一下:最简单的主意是将机密存储在二进制文件中,但是以某种方式混淆了,换句话说,就是存储了一个加密的机密。因此,这意味着您必须存储一个密钥来解密您的秘密,这似乎使我们花了整整一周的时间。但是,为什么不只使用操作系统中已经存在的密钥,即它是由操作系统而不是由您的应用程序定义的。

因此,要澄清我的想法是,选择操作系统定义的字符串,无论哪个字符串都没有关系。然后使用此字符串作为密钥加密您的秘密,并将其存储在您的应用程序中。然后在运行时,使用密钥(仅是OS常量)解密变量。窥视您的二进制文件的任何黑客都将看到一个加密的字符串,但没有密钥。

那行得通吗?


3
好主意,但没有。破解者只会看到指向OS常量地址的二进制文件。
GrayB 2011年



0

这些解决方案均不能阻止坚定的黑客嗅探从其移动设备(或仿真器)发送的数据包,以查看http标头中的客户端机密。

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

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


-2

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

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

为了获得秘密,必须获得对Android手机的root访问权限。


3
正如谁提到的?如果您是指戳的评论,请参阅我的答案,即秘密的==认证密钥。后者可以安全地存储,前者不能。我不了解Android,但是要获得对iPhone的root访问权并不难。请注意,该秘密在应用程序的所有实例上都是相同的,因此攻击者仅需获得对一个二进制文件的访问权限。即使他们无法在设备上获得root用户访问权限,也可以尝试使用其他二进制文件,并将秘密令牌从中取出。
Felixyz

1
只需添加它,也很容易将android手机
植根
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.