103

我正在尝试在使用 OAuth 2.0 的移动应用程序的 Web API 中实现委托授权。根据规范,隐式授权流程不支持刷新令牌,这意味着一旦在特定时间段内授予访问令牌,一旦令牌过期或被撤销,用户必须再次授予应用程序权限。

我想这对于在浏览器上运行的一些 javascript 代码来说是一个很好的场景,正如规范中提到的那样。我试图最小化用户必须授予应用程序权限以获取令牌的时间,因此看起来授权代码流是一个不错的选择,因为它支持刷新令牌。

但是,此流程似乎严重依赖 Web 浏览器来执行重定向。我想知道如果使用嵌入式 Web 浏览器,此流程对于移动应用程序是否仍然是一个不错的选择。还是我应该使用隐式流程?

4

5 回答 5

104

澄清:移动应用 = 原生应用

正如其他评论和一些在线资源中所述,隐式似乎很适合移动应用程序,但是最好的解决方案并不总是明确的(事实上,由于下面讨论的原因,不建议使用隐式)。

原生应用 OAuth2 最佳实践

无论您选择哪种方法(需要考虑一些权衡),您都应该注意此处概述的使用 OAuth2 的本机应用程序的最佳实践:https ://www.rfc-editor.org/rfc/rfc8252

考虑以下选项

隐式

我应该使用隐式吗?

引用第 8.2 节https://www.rfc-editor.org/rfc/rfc8252#section-8.2

OAuth 2.0 隐式授予授权流程(在 OAuth 2.0 [RFC6749] 的第 4.2 节中定义)通常适用于在浏览器中执行授权请求并通过基于 URI 的应用间通信接收授权响应的做法。
但是,由于隐式流不能被 PKCE [RFC7636](第 8.1 节要求)保护,因此不建议将隐式流与本机应用程序一起使用

通过隐式流程授予的访问令牌在没有用户交互的情况下也无法刷新,这使得授权代码授予流程(可以发出刷新令牌)成为需要刷新访问令牌的本机应用程序授权的更实用选项。

授权码

如果您确实使用授权代码,那么一种方法是通过您自己的 Web 服务器组件进行代理,该组件使用客户端密钥丰富令牌请求,以避免将其存储在设备上的分布式应用程序中。

以下摘录自:https ://dev.fitbit.com/docs/oauth2/

对于具有 Web 服务的应用程序,建议使用授权代码授予流程。此流程需要使用应用程序的客户端密钥进行服务器到服务器的通信。

注意:切勿将您的客户端机密放在分布式代码中,例如通过应用商店下载的应用程序或客户端 JavaScript。

没有 Web 服务的应用程序应使用隐式授予流程。

结论

在对入围的方法进行适当的风险评估并更好地理解其影响后,最终决定应考虑您所需的用户体验以及您对风险的偏好。

一个很好的阅读在这里https://auth0.com/blog/oauth-2-best-practices-for-native-apps/

另一个是https://www.oauth.com/oauth2-servers/oauth-native-apps/其中指出

当前的行业最佳实践是使用授权流程而忽略客户端密码,并使用外部用户代理来完成流程。外部用户代理通常是设备的本机浏览器(具有与本机应用程序不同的安全域),因此应用程序无法访问 cookie 存储或检查或修改浏览器内的页面内容。

PKCE 考虑

您还应该考虑此处描述的 PKCE https://www.oauth.com/oauth2-servers/pkce/

具体来说,如果您还实现了授权服务器,那么https://www.oauth.com/oauth2-servers/oauth-native-apps/checklist-server-support-native-apps/声明您应该

  • 允许客户端为其重定向 URL 注册自定义 URL 方案。
  • 支持具有任意端口号的环回 IP 重定向 URL,以支持桌面应用程序。
  • 不要假设原生应用程序可以保守秘密。要求所有应用声明它们是公开的还是机密的,并且只向机密应用发布客户端机密。
  • 支持 PKCE 扩展,并要求公共客户端使用它。
  • 尝试检测授权接口何时嵌入到本机应用程序的 Web 视图中,而不是在系统浏览器中启动,并拒绝这些请求。

Web 视图注意事项

在野外有很多使用 Web 视图的示例,即嵌入式用户代理,但应该避免这种方法(尤其是当应用程序不是第一方时),并且在某些情况下可能会导致您被禁止使用 API 作为摘录下面从这里演示

任何嵌入 OAuth 2.0 身份验证页面的尝试都将导致您的应用程序被 Fitbit API 禁止。

出于安全考虑,OAuth 2.0 授权页面必须显示在专用浏览器视图中。Fitbit 用户只有在拥有浏览器提供的工具(例如 URL 栏和传输层安全 (TLS) 证书信息)的情况下,才能确认他们正在使用真正的 Fitbit.com 网站进行身份验证。

对于本机应用程序,这意味着授权页面必须在默认浏览器中打开。本机应用程序可以使用自定义 URL 方案作为重定向 URI,将用户从浏览器重定向回请求权限的应用程序。

iOS 应用程序可以使用 SFSafariViewController 类而不是应用程序切换到 Safari。禁止使用 WKWebView 或 UIWebView 类。

Android 应用程序可能会使用 Chrome 自定义选项卡,而不是应用程序切换到默认浏览器。禁止使用 WebView。

为了进一步澄清,这里引用了上面提供的最佳实践链接的先前草案的这一部分

嵌入式用户代理,通常使用 web 视图实现,是授权原生应用程序的另一种方法。但是,根据定义,它们对于第三方使用是不安全的。它们涉及用户使用其完整登录凭据登录,只是将它们缩小为功能较弱的 OAuth 凭据。

即使在受信任的第一方应用程序使用时,嵌入式用户代理也违反了最小权限原则,因为它获得了比他们需要的更强大的凭据,这可能会增加攻击面。

在嵌入式用户代理的典型基于 Web 视图的实现中,主机应用程序可以: 记录在表单中输入的每一次击键以捕获用户名和密码;自动提交表格并绕过用户同意;复制会话 cookie 并使用它们以用户身份执行经过身份验证的操作。

鼓励用户在没有浏览器通常的地址栏和其他身份功能的情况下在嵌入式 Web 视图中输入凭据,这使得用户无法知道他们是否正在登录合法站点,即使登录了,它也会对他们进行培训无需先验证站点即可输入凭据。

除了安全问题之外,web-views 不会与其他应用程序或系统浏览器共享身份验证状态,需要用户为每个授权请求登录并导致糟糕的用户体验。

由于上述原因,不建议使用嵌入式用户代理,除非受信任的第一方应用充当其他应用的外部用户代理,或为多个第一方应用提供单点登录。

授权服务器应该考虑采取措施,在可能的情况下,通过不属于他们自己的嵌入式用户代理来检测和阻止登录。

这里还提出了一些有趣的观点:https ://security.stackexchange.com/questions/179756/why-are-developers-using-embedded-user-agents-for-3rd-party-auth-what-are-the-一个

于 2016-07-26T06:37:44.013 回答
27

Unfortunately, I don't think there is a clear answer to this question. However, here are the options that I've identified:

  • If it is ok to ask the user for his/her credentials, then use the Resource Owner Password Credentials. However, this may not be possible for some reasons, namely

    • Usability or security policies forbid the insertion of the password directly at the app
    • The authentication process is delegated on an external Identity Provider and must be performed via an HTTP redirect-based flow (e.g. OpenID, SAMLP or WS-Federation)
  • If usage of a browser based flow is required, then use the Authorization Code Flow. Here, the definition of the redirect_uri is a major challenge, for which there are the following options:

    • Use the technique described in https://developers.google.com/accounts/docs/OAuth2InstalledApp, where a special redirect_uri (e.g. urn:ietf:wg:oauth:2.0:oob) signals the authorization endpoint to show the authorization code instead of redirecting back to the client app. The user can manually copy this code or the app can try to obtain it from the HTML document title.
    • Use a localhost server at the device (the port management may not be easy).
    • Use a custom URI scheme (e.g. myapp://...) that when dereferenced triggers a registered "handler" (the details depend on the mobile platform).
    • If available, use a special "web view", such as the WebAuthenticationBroker on Windows 8, to control and access the HTTP redirect responses.

Hope this helps

Pedro

于 2013-07-02T14:41:52.330 回答
10

TL;DR:将授权码授予与PKCE一起使用

1. 隐式授权类型

隐式授权类型在移动应用程序中非常流行。但它不应该像这样使用。重定向存在安全问题。贾斯汀·里奇说

当您意识到与远程服务器 URL 不同时,问题就来了,没有可靠的方法来确保给定重定向 URI 和特定移动应用程序之间的绑定得到遵守。设备上的任何应用程序都可以尝试将自己插入重定向过程并使其提供重定向 URI。猜猜看:如果您在本机应用程序中使用了隐式流,那么您只是将您的访问令牌交给了攻击者。从那时起没有任何恢复——他们得到了令牌并且可以使用它。

再加上它不允许您刷新访问令牌的事实,最好避免使用它。

2.授权码授予类型

授权码授予需要客户端密码。但是您不应该在移动应用程序的源代码中存储敏感信息。人们可以提取它们。为了不暴露客户端机密,您必须像Facebook 所写的那样将服务器作为中间人运行:

我们建议仅应直接从您的应用服务器使用应用访问令牌,以提供最佳安全性。对于原生应用,我们建议应用与您自己的服务器通信,然后服务器使用应用访问令牌向 Facebook 发出 API 请求。

这不是一个理想的解决方案,但有一种新的、更好的在移动设备上进行 OAuth 的方法:代码交换的证明密钥

3. PKCE(Proof Key for Code Exchange)的授权码授予类型

出于限制,创建了一种新技术,使您可以在没有客户端密码的情况下使用授权代码。您可以阅读完整的RFC 7636这个简短的介绍

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

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

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

于 2018-03-06T14:13:18.200 回答
-4

Using a webview in your mobile application should be an affordable way to implement OAuth2.0 protocol on Android platform.

As for redirect_uri field, I think http://localhost is a good choice and you don't have to port a HTTP server inside your application, because you can override the implementation of onPageStarted function in the WebViewClient class and stop loading the web page from http://localhost after you check the url parameter.

public void onPageStarted(final WebView webView, final String url,
        final Bitmap favicon) {}
于 2015-02-20T18:58:12.353 回答
-5

最流畅的身份验证用户体验,最容易实现的就是在你的应用程序中嵌入一个 webview。处理 webview 从身份验证点收到的响应并检测错误(用户取消)或批准(并从 url 查询参数中提取令牌)。我认为你实际上可以在所有平台上做到这一点。我已经成功地完成了以下工作:ios、android、mac、windows store 8.1 应用程序、windows phone 8.1 应用程序。我为以下服务执行此操作:dropbox、google drive、onedrive、box、basecamp。对于非 Windows 平台,我使用的是 Xamarin,据说它不会公开整个平台特定的 API,但它确实公开了足够多的内容以使这成为可能。因此,即使从跨平台的角度来看,它也是一个非常易于使用的解决方案,而您不需要

于 2015-02-17T21:55:37.097 回答