什么是适用于移动应用的OAuth 2.0流程


87

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

我猜这对于规范中提到的在浏览器上运行的某些javascript代码是一个好方案。我正在尝试最小化用户必须授予应用程序权限以获得令牌的时间,因此授权代码流似乎是一个不错的选择,因为它支持刷新令牌。

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


1
问题是-像最高优先级一样,用户永远不需要在首次登录后再次输入密码吗?
minimumprivilege

是的,这正是我的要求。用户应该只键入一次密码。但是,我不想设置具有无限生存期的令牌并将其保留在移动应用程序中,因为这将与吊销令牌的能力背道而驰。(除非我在移动应用中添加了一些逻辑以检测到该请求是未经授权的,所以之后我请求一个新令牌)
Pablo Cibraro

1
您可以添加具有无限生存期的令牌,但仍然可以将其吊销。是的,应用程序逻辑应该能够检测到这一点。RFC 6750定义了一种检查错误是否是由于吊销令牌引起的方法。
Pedro Felix

1
请避免使用网络视图(除非您拥有全部堆栈,并且不使用社交登录名),否则有可能破坏密码。当第三方嵌入式用户代理要求我提供凭据时,我将卸载该应用程序。某些API现在甚至禁止这样的集成,如这一个dev.fitbit.com/docs/oauth2我提供了另一个答案,以进一步澄清一些概念(stackoverflow.com/a/38582630/752167
马特Ç

Answers:


90

说明:移动应用=本地应用

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

本机应用OAuth2最佳做法

无论选择哪种方法(都需要权衡考虑),都应注意此处概述的使用OAuth2的本机应用程序的最佳做法:https : //tools.ietf.org/html/rfc8252

考虑以下选项

隐含的

我应该使用隐式吗?

引用第8.2节https://tools.ietf.org/html/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 Views的示例,例如嵌入式用户代理,但应避免使用这种方法(特别是在应用不是第一方的情况下),在某些情况下,可能会导致您被禁止使用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视图不会与其他应用程序或系统浏览器共享身份验证状态,这要求用户针对每个授权请求登录,并导致不良的用户体验。

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

授权服务器应考虑采取步骤,在可能的情况下,通过不是自己的嵌入式用户代理来检测和阻止登录。

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


3
谷歌是在4月20日消除对网页视图的支持,2017年developers.googleblog.com/2016/08/...
马特ç

仅供参考,如果该文件尚未起草,则本答案开头将引用本机应用程序的OAuth 2.0-tools.ietf.org/html/rfc8252
Kostiantyn

感谢@KostiantynSokolinskyi,对其进行了相应编辑,并提供了不再是草案的rfc链接
Matt C

@MattC实施新用户注册的最佳方法是什么?我们应该在应用程序中还是在IDP上进行操作?是否可以自动登录用户帖子注册?stackoverflow.com/questions/60187173/...
Yashvit

抱歉,我对某些细节感到困惑...请您看看吗?谢谢!链接---> stackoverflow.com/q/61313694/4619958
ch271828n

25

不幸的是,我认为这个问题没有明确的答案。但是,这是我确定的选项:

  • 如果可以要求用户提供其凭据,请使用“资源所有者密码凭据”。但是,由于某些原因,这可能无法实现,即

    • 可用性或安全策略禁止在应用程序中直接插入密码
    • 身份验证过程在外部身份提供者上委派,并且必须通过基于HTTP重定向的流(例如,OpenID,SAMLP或WS-Federation)执行
  • 如果需要使用基于浏览器的流程,请使用授权代码流程。在此,的定义redirect_uri是一个重大挑战,为此,可以选择以下选项:

    • 使用https://developers.google.com/accounts/docs/OAuth2InstalledApp中描述的技术,其中特殊的redirect_uri(例如urn:ietf:wg:oauth:2.0:oob)向授权端点发出信号以显示授权代码,而不是重定向回客户端应用程序。用户可以手动复制此代码,或者应用程序可以尝试从HTML文档标题中获取它。
    • 用一个 localhost在设备上服务器(端口管理可能不容易)。
    • 使用自定义URI方案(例如myapp://...),该方案在取消引用时会触发注册的“处理程序”(详细信息取决于移动平台)。
    • 如果可用,请使用特殊的“ Web视图”,例如Windows 8上的WebAuthenticationBroker,以控制和访问HTTP重定向响应。

希望这可以帮助

佩德罗


感谢Pedro的投入!是的,看起来带有自定义URI方案的授权代码流或Web视图似乎是此处的最佳选择。
Pablo Cibraro

1
这完全取决于您是否希望客户端在Web视图或客户端应用程序中键入密码。如果可能的话,我希望使用客户端应用程序-然后立即用访问/刷新令牌交换秘密。
minimumprivilege

谢谢多米尼克!我的客户正在使用ADFS对用户进行身份验证,因此他们想在登录页面中输入凭据。网络视图将为他们工作
Pablo Cibraro

5
我很好奇为什么您会推荐“授权代码流”?您是否不需要client_secret和client_id来将代码交换为access_token?我认为“隐式”流程是针对这些情况设计的,因为它不需要将秘密存储在设备中。
Eugenio Pace 2013年

1
隐式不支持刷新令牌OOB。在Pablo的情况下-我显然会推荐RO流程。听起来像公司针对同一公司后端部署了应用程序。
minimumprivilege

9

TL; DR:PKCE中使用授权码授予

1.隐式赠款类型

隐式授予类型在移动应用程序中非常流行。但这并不是要像这样使用。重定向周围存在安全隐患。贾斯汀·里希(Justin Richer)说

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

同时,它不允许您刷新访问令牌,因此最好避免使用它。

2.授权码授予类型

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

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

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

3.带有PKCE(代码交换证明密钥)的授权代码授予类型

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

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

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

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


-3

在移动应用程序中使用Webview应该是在Android平台上实现OAuth2.0协议的一种经济实惠的方法。

至于redirect_uri字段,我认为这http://localhost是一个不错的选择,您不必在应用程序内部移植HTTP服务器,因为您可以覆盖该类中onPageStarted函数的实现,WebViewClienthttp://localhost在检查url参数后停止加载网页。

public void onPageStarted(final WebView webView, final String url,
        final Bitmap favicon) {}

3
使用OAuth2的本机应用程序的最佳做法:tools.ietf.org/html/draft-wdenniss-oauth-native-apps
Matt C

1
正如Matt C所说。Web视图对于移动应用程序不是一个好主意-它们不安全,允许应用程序访问凭据(因此比RO更安全),并且不允许用户验证域和TLS证书。将Auth Code授权类型与自定义URI处理程序结合使用,并确保您使用的是密钥交换证明(PKCE),以阻止手机上的恶意应用拦截Auth代码并获得对API的访问权限。
ChrisC'8

2
OAuth 2.0 for Native Apps最佳做法文档草案的更新版本位于tools.ietf.org/html/draft-ietf-oauth-native-apps
Jeff Olson

-4

进行身份验证时最顺畅的用户体验,最容易实现的是在您的应用中嵌入Web视图。处理Webview从身份验证点收到的响应,并检测错误(用户取消)或批准(并从url查询参数中提取令牌)。而且我认为您实际上可以在所有平台上做到这一点。我已成功完成以下工作:iOS,Android,Mac,Windows Store 8.1应用程序,Windows Phone 8.1应用程序。我这样做是为了以下服务:投寄箱,Google驱动器,onedrive,box,basecamp。对于非Windows平台,我使用的Xamarin可能不会公开整个平台特定的API,但是确实提供了足够的公开信息来实现这一点。因此,即使从跨平台的角度来看,这也是一个非常易于访问的解决方案,而您不会


在提供便利的用户体验的同时,我们将看到行业逐渐摆脱这种方法。当网络视图打开时,可能会破坏密码,当嵌入式用户代理要求我提供凭据时,我将卸载该应用程序。现在有些API甚至禁止此类集成,例如这一dev.fitbit.com/docs/oauth2
Matt C

使用OAuth2的本机应用程序的最佳做法:tools.ietf.org/html/draft-wdenniss-oauth-native-apps
Matt C

我看不到启用oauth的服务如何禁止这种方法。它不可检测且安全。...一些启用oauth的服务提供特定于平台的客户端以简化身份验证,而这些客户端实际上执行了我在此描述的操作(显示嵌入式Webview和跟踪url更改)。您链接的最佳实践建议您做同样的事情:使用系统浏览器或嵌入式Webview。你从我的回应中攻击什么论点?目前尚不清楚。
Radu Simionescu '16

无意发动攻击,只是突出问题。该链接表示您提到了2种方法,但是只有外部用户代理才被认为是安全的,特别是它表示本机应用程序的选项是“通过嵌入式用户代理或外部用户代理。此文档建议使用外部用户代理。应用内浏览器标签等用户代理是OAuth唯一安全且可用的选择。”
Matt C

进一步引用“在嵌入式用户代理的典型基于Web视图的实现中,主机应用程序可以:记录在表单中输入的每个击键以捕获用户名和密码;自动提交表单并跳过用户同意”。 “不建议使用嵌入式用户代理,除非受信任的第一方应用充当其他应用的外部用户代理,或者为多个第一方应用提供单点登录。授权服务器应考虑采取以下措施:在可能的情况下,通过不是自己的嵌入式用户代理来检测和阻止登录。”
Matt C
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.