Android 移动应用程序中的 OAuth 秘密

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1934187/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 03:50:23  来源:igfitidea点击:

OAuth secrets in mobile apps

iphoneandroidsecuritymobileoauth

提问by Felixyz

When using the OAuth protocol, you need a secret string obtained from the service you want to delegate to. If you are doing this in a web app, you can simply store the secret in your data base or on the file system, but what is the best way to handle it in a mobile app (or a desktop app for that matter)?

使用 OAuth 协议时,您需要从要委托给的服务中获取一个秘密字符串。如果您在 Web 应用程序中执行此操作,您可以简单地将机密存储在您的数据库或文件系统中,但是在移动应用程序(或桌面应用程序)中处理它的最佳方法是什么?

Storing the string in the app is obviously not good, as someone could easily find it and abuse it.

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

Another approach would be to store it on your server, and have the app fetch it on every run, never storing it on the phone. This is almost as bad, because you have to include the URL in the app.

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

The only workable solution I can come up with is to first obtain the Access Token as normal (preferably using a web view inside the app), and then route all further communication through our server, which would append the secret to the request data and communicate with the provider. Then again, I'm a security noob, so I'd really like to hear some knowledgeable peoples' opinions on this. It doesn't seem to me that most apps are going to these lengths to guarantee security (for example, Facebook Connect seems to assume that you put the secret into a string right in your app).

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

Another thing: I don't believe the secret is involved in initially requesting the Access Token, so that could be done without involving our own server. Am I correct?

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

采纳答案by Zac Bowling

Yes, this is an issue with the OAuth design that we are facing ourselves. We opted to proxy all calls through our own server. OAuth wasn't entirely flushed out in respect of desktop apps. There is no prefect solution to the issue that I've found without changing OAuth.

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

If you think about it and ask the question why we have secrets, is mostly for provision and disabling apps. If our secret is compromised, then the provider can only really revoke the entire app. Since we have to embed our secret in the desktop app, we are sorta screwed.

如果您考虑一下并询问我们为什么拥有机密的问题,主要是为了提供和禁用应用程序。如果我们的秘密被泄露,那么提供商只能真正撤销整个应用程序。由于我们必须在桌面应用程序中嵌入我们的秘密,我们有点搞砸了。

The solution is to have a different secret for each desktop app. OAuth doesn't make this concept easy. One way is have the user go and create an secret on their own and enter the key on their own into your desktop app (some facebook apps did something similar for a long time, having the user go and create facebook to setup their custom quizes and crap). It's not a great experience for the user.

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

I'm working on proposal for a delegation system for OAuth. The concept is that using our own secret key we get from our provider, we could issue our own delegated secret to our own desktop clients (one for each desktop app basically) and then during the auth process we send that key over to the top level provider that calls back to us and re-validates with us. That way we can revoke on own secrets we issue to each desktop client. (Borrowing a lot of how this works from SSL). This entire system would be prefect for value-add webservices as well that pass on calls to a third party webservice.

我正在研究 OAuth 委托系统的提案。这个概念是,使用我们从提供商那里获得的自己的秘密密钥,我们可以向我们自己的桌面客户端发布我们自己的委托秘密(基本上每个桌面应用程序一个),然后在身份验证过程中我们将该密钥发送到顶级回调给我们并与我们重新验证的提供商。这样我们就可以撤销我们发布给每个桌面客户端的自己的秘密。(从 SSL 借用了很多这是如何工作的)。整个系统将非常适合增值网络服务以及将调用传递给第三方网络服务。

The process could also be done without delegation verification callbacks if the top level provider provides an API to generate and revoke new delegated secrets. Facebook is doing something similar by allowing facebook apps to allow users to create sub-apps.

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

There are some talks about the issue online:

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

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

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

Twitter and Yammer's solution is a authentication pin solution: https://dev.twitter.com/oauth/pin-basedhttps://www.yammer.com/api_oauth_security_addendum.html

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

回答by Dick Hardt

With OAUth 2.0, you can store the secret on the server. Use the server to acquire an access token that you then move to the app and you can make calls from the app to the resource directly.

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

With OAuth 1.0 (Twitter), the secret is required to make API calls. Proxying calls through the server is the only way to ensure the secret is not compromised.

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

Both require some mechanism that your server component knows it is your client calling it. This tends to be done on installation and using a platform specific mechanism to get an app id of some kind in the call to your server.

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

(I am the editor of the OAuth 2.0 spec)

(我是 OAuth 2.0 规范的编辑)

回答by Jayesh

One solution could be to hard code the OAuth secret into the code, but notas a plain string. Obfuscate it in some way - split it into segments, shift characters by an offset, rotate it - do any or all of these things. A cracker can analyse your byte code and find strings, but the obfuscation code might be hard to figure out.

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

It's not a foolproof solution, but a cheap one.

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

Depending on the value of the exploit, some genius crackers can go to greater lengths to find your secret code. You need to weigh the factors - cost of previously mentioned server side solution, incentive for crackers to spend more efforts on finding your secret code, and the complexity of the obfuscation you can implement.

根据漏洞利用的价值,一些天才破解者可以竭尽全力找到您的密码。您需要权衡各种因素 - 前面提到的服务器端解决方案的成本、促使破解者花费更多精力寻找您的密码的动机,以及您可以实施的混淆的复杂性。

回答by Gudradain

Do not store the secret inside the application.

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

You need to have a server that can be accessed by the application over https(obviously) and you store the secret on it.

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

When someone want to login via your mobile/desktop application, your application will simply forward the request to the server that will then append the secret and send it to the service provider. Your server can then tell your application if it was successful or not.

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

Then if you need to get any sensitive information from the service (facebook, google, twitter, etc), the application ask your server and your server will give it to the application only if it is correctly connected.

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

There is not really any option except storing it on a server. Nothing on the client side is secure.

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

Note

笔记

That said, this will only protect you against malicious client but not client against malicious you and not client against other malicious clients (phising)...

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

OAuth is a much better protocol in browser than on desktop/mobile.

OAuth 是浏览器中比桌面/移动更好​​的协议。

回答by Johannes Filter

There is a new extension to the Authorization Code Grant Type called Proof Key for Code Exchange (PKCE). With it, you don't need a client secret.

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

PKCE (RFC 7636) is a technique to secure public clients that don't use a client secret.

It is primarily used by native and mobile apps, but the technique can be applied to any public client as well. It requires additional support by the authorization server, so it is only supported on certain providers.

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

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

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

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

For more information, you can read the full RFC 7636or this short introduction.

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

回答by YiddishNinja

Here's something to think about. Google offers two methods of OAuth... for web apps, where you register the domain and generate a unique key, and for installed apps where you use the key "anonymous".

这里有一些事情需要考虑。Google 提供了两种 OAuth 方法......用于网络应用程序,您可以在其中注册域并生成唯一密钥,以及用于使用“匿名”密钥的已安装应用程序。

Maybe I glossed over something in the reading, but it seems that sharing your webapp's unique key with an installed app is probably more secure than using "anonymous" in the official installed apps method.

也许我在阅读中掩盖了一些东西,但似乎与已安装的应用程序共享您的 web 应用程序的唯一密钥可能比在官方安装的应用程序方法中使用“匿名”更安全。

回答by Joel Richard

With OAuth 2.0 you can simply use the client side flow to obtain an access token and use then this access token to authenticate all further requests. Then you don't need a secret at all.

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

A nice description of how to implement this can be found here: https://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified#mobile-apps

关于如何实现这一点的一个很好的描述可以在这里找到:https: //aaronparecki.com/articles/2012/07/29/1/oauth2-simplified#mobile-apps

回答by oliland

Facebook doesn't implement OAuth strictly speaking (yet), but they have implemented a way for you not to embed your secret in your iPhone app: https://web.archive.org/web/20091223092924/http://wiki.developers.facebook.com/index.php/Session_Proxy

Facebook 严格来说(还)没有实施 OAuth,但他们已经实施了一种方法,让您不要将您的秘密嵌入您的 iPhone 应用程序:https: //web.archive.org/web/20091223092924/http: //wiki。 developer.facebook.com/index.php/Session_Proxy

As for OAuth, yeah, the more I think about it, we are a bit stuffed. Maybe thiswill fix it.

至于OAuth,是的,我想得越多,我们就有些吃力了。也许会解决它。

回答by Martin Bayly

I agree with Felixyz. OAuth whilst better than Basic Auth, still has a long way to go to be a good solution for mobile apps. I've been playing with using OAuth to authenticate a mobile phone app to a Google App Engine app. The fact that you can't reliably manage the consumer secret on the mobile device means that the default is to use the 'anonymous' access.

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

The Google App Engine OAuth implementation's browser authorization step takes you to a page where it contains text like: "The site <some-site> is requesting access to your Google Account for the product(s) listed below"

Google App Engine OAuth 实现的浏览器授权步骤会将您带到包含以下文本的页面:“站点 <some-site> 正在请求访问您的 Google 帐户以获取下面列出的产品”

YourApp(yourapp.appspot.com) - not affiliated with Google

YourApp(yourapp.appspot.com) - 不隶属于 Google

etc

等等

It takes <some-site> from the domain/host name used in the callback url that you supply which can be anything on the Android if you use a custom scheme to intercept the callback. So if you use 'anonymous' access or your consumer secret is compromised, then anyone could write a consumer that fools the user into giving access to your gae app.

它从您提供的回调 url 中使用的域/主机名中获取 <some-site> ,如果您使用自定义方案拦截回调,它可以是 Android 上的任何内容。因此,如果您使用“匿名”访问或您的消费者机密被泄露,那么任何人都可以编写一个消费者来欺骗用户授予对您的 gae 应用程序的访问权限。

The Google OAuth authorization page also does contain lots of warnings which have 3 levels of severity depending on whether you're using 'anonymous', consumer secret, or public keys.

Google OAuth 授权页面还包含许多警告,根据您使用的是“匿名”、消费者秘密还是公钥,这些警告具有 3 级严重性。

Pretty scary stuff for the average user who isn't technically savvy. I don't expect to have a high signup completion percentage with that kind of stuff in the way.

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

This blog post clarifies how consumer secret's don't really work with installed apps. http://hueniverse.com/2009/02/should-twitter-discontinue-their-basic-auth-api/

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

回答by Daniel Thorpe

I'm also trying to come up with a solution for mobile OAuth authentication, and storing secrets within the application bundle in general.

我还尝试为移动 OAuth 身份验证提出解决方案,并在应用程序包中存储秘密。

And a crazy idea just hit me: The simplest idea is to store the secret inside the binary, but obfuscated somehow, or, in other words, you store an encrypted secret. So, that means you've got to store a key to decrypt your secret, which seems to have taken us full circle. However, why not just use a key which is already in the OS, i.e. it's defined by the OS not by your application.

一个疯狂的想法突然袭击了我:最简单的想法是将秘密存储在二进制文件中,但以某种方式进行了混淆,或者换句话说,您存储了一个加密的秘密。所以,这意味着你必须存储一个密钥来解密你的秘密,这似乎让我们绕了一圈。但是,为什么不直接使用操作系统中已有的密钥,即它是由操作系统定义的,而不是由您的应用程序定义的。

So, to clarify my idea is that you pick a string defined by the OS, it doesn't matter which one. Then encrypt your secret using this string as the key, and store that in your app. Then during runtime, decrypt the variable using the key, which is just an OS constant. Any hacker peeking into your binary will see an encrypted string, but no key.

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

Will that work?

那行得通吗?