OAuth 2中隐式授权授权类型的目的是什么?

Dan*_*lin 242 user-agent oauth oauth-2.0

我不知道我是否只是有某种盲点或什么,但我已多次阅读OAuth 2规范并仔细阅读邮件列表档案,我还没有找到一个很好的解释为什么隐含格兰特已经开发出用于获得访问令牌的流程.与授权代码授予相比,似乎只是放弃了客户端身份验证,没有非常令人信服的理由.这是如何"针对使用脚本语言在浏览器中实现的客户端进行优化"(引用规范)?

两个流程都是相同的(来源:http://tools.ietf.org/html/draft-ietf-oauth-v2-22):

  1. 客户端通过将资源所有者的用户代理指向授权端点来启动流.
  2. 授权服务器对资源所有者进行身份验证(通过用户代理),并确定资源所有者是否授予或拒绝客户端的访问请求.
  3. 假设资源所有者授予访问权限,授权服务器使用先前提供的重定向URI(在请求中或在客户端注册期间)将用户代理重定向回客户端.
    • 重定向URI包括授权代码(授权代码流)
    • 重定向URI包括URI片段中的访问令牌(隐式流)

这是流量分裂的地方.在这两种情况下,此时重定向URI都是由客户端托管的某个端点:

  • 在授权代码流中,当用户代理使用URI中的授权代码命中该端点时,该端点上的代码会将授权代码及其客户端凭据交换为访问令牌,然后可以根据需要使用该令牌.例如,它可以将其写入页面上的脚本可以访问的网页中.
  • Implicit流完全跳过此客户端身份验证步骤,只是加载带有客户端脚本的网页.这里有一个可爱的技巧,URL片段可以防止访问令牌过多传递,但最终结果基本相同:客户端托管的站点提供一个页面,其中包含一些可以获取访问令牌的脚本.

因此我的问题是:通过跳过客户端身份验证步骤获得了什么?

小智 191

这是我的想法:

授权代码流中的auth代码+令牌的目的是令牌和客户端机密永远不会暴露给资源所有者,因为它们在服务器到服务器之间传播.

另一方面,隐式授权流程适用于完全使用javascript实现且在资源所有者的浏览器中运行的客户端.您不需要任何服务器端代码来使用此流程.然后,如果资源所有者的浏览器中发生了所有事情,则再发出身份验证代码和客户端密钥是没有意义的,因为令牌和客户端密钥仍将与资源所有者共享.包括身份验证代码和客户端密钥只会使流程更加复杂,而不会增加任何真正的安全性.

所以答案是"已经获得了什么?" 是"简单".

  • 谢谢.这是一个很好的观点,在授权代码流中,资源所有者永远不需要看到访问令牌,而在javascript客户端中这是不可避免的.仍然可以使用授权代码流从javascript客户端保留客户端机密,但是:在验证并获得访问令牌之后,服务器端代码然后将令牌传递给javascript客户端.我现在看到的是,隐式授权流程可以分发javascript oauth SDK,比如Facebook,让开发人员不必完全编写自己的oauth代码. (4认同)
  • 我想补充一点,授权代码流使客户能够存储令牌并重用它们.在隐式流程中,您并不总是拥有该选项,因此,隐式流程是安全级别和便利性之间的实用选择. (3认同)
  • 我不认为这是一个全面的答案,隐式流程并非旨在获得简单优势,而是破坏客户端应用程序的安全问题.`auth code`,与`client_id`和`client_secret`一起用于识别可以刷新令牌长时间登录和["离线登录"]的可信客户端(/sf/ask/2144658911/ -does - 离线访问功能于OAuth的平均值).但是在客户端应用程序中,无法注册每个客户端,因此临时访问用户信息的"简化"隐式授权类型 (3认同)
  • 这只能回答一半,“什么丢失了”? (2认同)
  • 包含客户端密钥不仅会使流程更加复杂,还会使其“安全性降低”。如果需要在客户端代码中枚举客户端密钥,那么它就不是秘密,因此它会暴露在互联网上。如果您的客户端 ID 仅在隐式流中使用,这不是问题。但如果它也在平台的其他地方用于刷新令牌或授权代码授予,那么暴露相应的秘密就是一个大问题。 (2认同)

art*_*nig 90

这是出于安全原因,而不是为了简单起见.

您应该考虑用户代理客户端之间的区别:

用户代理是用户("资源所有者")与系统的其他部分(认证服务器和资源服务器)通信的软件.

客户端是想要访问资源服务器上的用户资源的软件.

在解耦用户代理和客户端的情况下,授权代码授权是有意义的.例如,用户使用Web浏览器(用户代理)在Kickstarter上使用他的Facebook帐户登录.在这种情况下,客户端是Kickstarter的服务器之一,它处理用户登录.此服务器从Facebook获取访问令牌和刷新令牌.因此,这种类型的客户端被认为是"安全的",由于访问受限,可以保存令牌并且Kickstarter可以访问用户的资源甚至刷新访问令牌而无需用户交互.

如果用户代理和客户端耦合(例如,本机移动应用程序,javascript应用程序),则可以应用隐式授权工作流程.它依赖于资源所有者的存在(用于输入凭据),并且不支持刷新令牌.如果此客户端存储访问令牌供以后使用,则会出现安全问题,因为该令牌可以被其他应用程序或客户端用户轻松提取.缺少刷新令牌是一个额外的提示,该方法不是为在没有用户的情况下访问用户资源而设计的.

  • 我看到我的浏览器已登录我的谷歌帐户数月.谷歌是否在浏览器上使用访问令牌或访问令牌有很长的到期时间?具有较长过期时间的访问令牌与访问令牌之间的使用有何不同?任何其他客户端都可以捕获访问令牌,并在资源所有者不存在时使用它. (2认同)

JW.*_*JW. 59

通常的解释是,当您使用JavaScript客户端时,隐式授权更容易实现.但我认为这是错误的观察方式.如果您使用的是直接通过XMLHttpRequest请求受保护资源的JavaScript客户端,则隐式授权是您唯一的选择,尽管它不太安全.

授权代码授予提供了额外的安全性,但只有在Web服务器请求受保护资源时才有效.由于Web服务器可以存储访问令牌,因此访问令牌暴露给Internet的风险较小,您可以发出持续时间较长的令牌.由于Web服务器是可信任的,因此可以为其提供"刷新令牌",因此当旧服务器到期时它可以获得新的访问令牌.

但是 - 这一点很容易被遗漏 - 授权代码流的安全性只有在Web服务器受到会话保护时才有效,该会话是通过用户身份验证(登录)建立的.如果没有会话,不受信任的用户可以使用client_id向Web服务器发出请求,这与用户拥有访问令牌的情况相同.添加会话意味着只有经过身份验证的用户才能访问受保护的资源.client_id只是JS webapp的"身份",而不是所述webapp的身份验证.

这也意味着您可以在OAuth令牌过期之前结束会话.没有标准的方法来使访问令牌无效.但是如果你的会话到期,访问令牌就没用了,因为除了web服务器之外没有人知道它.如果不受信任的用户获得了对会话密钥的访问权限,则只要会话有效,他们就只能访问受保护的资源.

如果没有Web服务器,则必须使用隐式授权.但这意味着访问令牌暴露给Internet.如果不受信任的用户获得对它的访问权限,他们可以使用它直到它过期.这意味着他们可以访问它的时间比授权代码授权更长.因此,您可能需要考虑尽快使令牌过期,并避免访问更敏感的资源.


Wil*_*ill 21

它归结为:如果用户正在运行基于浏览器或"公共"(JavaScript)的Web应用程序而没有服务器端组件,则用户会隐式信任该应用程序(以及运行它的浏览器,可能还有其他浏览器)基于应用程序...).

没有第三方远程服务器,只有资源服务器.授权代码没有任何好处,因为除了代表用户的浏览器之外,没有其他代理.出于同样的原因,客户端凭据没有任何好处.(任何客户端都可以尝试使用此流程.)

然而,安全隐患很重要.来自http://tools.ietf.org/html/rfc6749#section-10.3:

当使用隐式授权类型时,访问令牌在URI片段中传输,这可以将其暴露给未授权方.

来自http://tools.ietf.org/html/rfc6749#section-10.16:

资源所有者可以通过向攻击者的恶意客户端授予访问令牌来自愿委派对资源的访问权.这可能是由于网络钓鱼或其他一些借口......

  • @ZammyPage,这通常称为单页应用程序(SPA)。该应用程序的整体由静态资源提供。然后,应用程序中的Javascript可动态访问它可以访问的资源服务器上所需的任何资源。没有服务器生成客户端的内容:客户端中的javascript根据需要修改DOM,以表示其已访问的资源。 (2认同)

tzu*_*hiu 13

我不确定我是否正确理解答案和Dan的评论.在我看来,答案已经说明了一些事实是正确的,但它确实指出了OP所要求的.如果我理解正确,隐式授权流程的主要优点是像JS应用程序(例如Chrome扩展程序)这样的客户端不必公开客户端密钥.

丹塔夫林说:

...在授权代码流中,资源所有者永远不需要查看访问令牌,而在javascript客户端中这是不可避免的.仍然可以使用授权代码流从javascript客户端保留客户端密钥,但..

也许我误解了你,但是客户端(在这种情况下是JS应用程序)必须将客户端凭证(客户端密钥和密钥)传递给授权代码流中的资源服务器,对吧?客户端密钥不能"保留JS".

  • 我意识到这是一个古老的问题,但这是一个比接受的更好的答案.隐式授权存在的原因是javascript客户端无法保密,因此无法进行身份验证.因此,授权服务器必须依赖*重定向uri注册和用户代理以确保安全性.您只将授权令牌传递给用户代理,并且仅在特定的重定向uri上传递,理论上可以防止拦截(因为不拥有重定向uri域的恶意用户无法在该用户代理中执行代码). (6认同)

Gro*_*ify 8

虽然Implicit Grant旨在支持无法保护客户端密钥(包括客户端JavaScript应用程序)的应用程序,但某些提供商正在使用授权代码而不使用客户端密钥来实现替代方案.OAuth 2.0 IETF RFC-6749于2012年发布,目前的建议是最近的一些讨论来自2017年.

这些实施者可以在2017年讨论IETF OAuth邮件列表:

在这里阅读更多:

之前建议客户使用Implicit,但没有保密,但已被使用授权代码授权所取代.

...

以前,建议基于浏览器的应用程序使用"隐式"流程,该流程会立即返回访问令牌,并且没有令牌交换步骤.自规范最初编写以来,行业最佳实践已经改变,建议在没有客户机密的情况下使用授权代码流.这为创建安全流提供了更多机会,例如使用state参数.参考文献:Redhat,Deutsche Telekom,Smart Health IT.

移动应用程序还提到了从隐式授权转移到没有Client Secret的Auth Code:


Pac*_*ace 5

在隐式流程中,如果用户的浏览器已损坏(邪恶扩展/病毒),则损坏会访问用户的资源并可能做坏事。

在身份验证流程中,腐败不能,因为它不知道客户端秘密。