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

我不知道我是否有某种盲点或其他原因,但我已经多次阅读OAuth 2规范,并仔细阅读了邮件列表存档,但我还没有找到一个很好的解释,为什么开发了用于获取访问令牌的隐式授权流。与授权代码授权相比,它似乎只是因为没有非常令人信服的原因而放弃了客户端身份验证。如何在浏览器中使用脚本语言对客户端进行优化?(引用说明书)?

两个流开始时是相同的(来源:https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-22):

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

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

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

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

84015 次浏览

以下是我的想法:

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

另一方面,隐式授权流适用于完全使用javascript实现并在资源所有者的浏览器中运行的客户端。使用此流不需要任何服务器端代码。然后,如果一切都发生在资源所有者的浏览器,它没有意义的发布认证代码&客户端不再是秘密了,因为token &客户端秘密仍将与资源所有者共享。包括认证代码&客户端保密只会使流程更加复杂,而不会增加任何真正的安全性。

因此,关于“我们获得了什么?”的答案是“简单”。

我不确定我是否正确理解了答案和丹的评论。在我看来,这个答案已经陈述了一些正确的事实,但它确实指出了OP所问的问题。如果我理解正确的话,隐式授权流的主要优势是像JS应用程序这样的客户端(例如Chrome扩展)不需要暴露客户端秘密。

丹·塔夫林说:

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

也许我误解了您的意思,但是客户端(在本例中是JS应用程序)必须在授权代码流中将客户端凭证(客户端密钥和秘密)传递给资源服务器,对吗?客户端机密不能“对JS保密”。

它可以归结为:如果用户正在运行一个基于浏览器的,或“public”(JavaScript) web应用程序,没有服务器端组件,那么用户隐式信托基金应用程序(和它运行的浏览器,可能与其他基于浏览器的应用程序…)

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

然而,这对安全的影响是重大的。从https://www.rfc-editor.org/rfc/rfc6749#section-10.3:

当使用隐式授权类型时,访问令牌在

. URI片段,这可能会将其暴露给未授权方

https://www.rfc-editor.org/rfc/rfc6749#section-10.16:

资源所有者可以自愿将对资源的访问委托给 向攻击者的恶意客户端授予访问令牌。这可能 可能是因为网络钓鱼或其他借口…

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

授权码授权提供了额外的安全性,但它仅在web服务器请求受保护资源时才有效。由于web服务器可以存储访问令牌,因此访问令牌暴露在Internet上的风险较小,并且可以发出持续较长时间的令牌。由于web服务器是受信任的,所以可以给它一个“刷新令牌”,所以当旧的访问令牌过期时,它可以获得一个新的访问令牌。

但是——这是很容易忽略的一点——授权代码流的安全性只有在web服务器受到会话保护的情况下才有效,会话是通过用户身份验证(登录)建立的。如果没有会话,不受信任的用户可以使用client_id向web服务器发出请求,这与用户拥有访问令牌是一样的。添加会话意味着只有通过认证的用户才能访问受保护的资源。client_id只是JS webapp的“身份”,而不是该webapp的身份验证。

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

如果没有网络服务器,你必须使用隐式授权。但这意味着访问令牌暴露在Internet上。如果一个不受信任的用户获得了它的访问权限,他们可以使用它直到过期。这意味着他们将拥有比授权代码授予更长的访问时间。因此,您可能需要考虑让令牌提前过期,并避免授予对更敏感资源的访问权。

最近,人们建议你避免使用隐式授权,即使是在没有服务器的web应用程序上。相反,您可以使用配置了空秘密的授权码授权以及PKCE。auth-code授权避免将访问令牌存储在浏览器历史记录中,如果有人劫持重定向URL以窃取身份验证代码,PKCE避免暴露它。在这种情况下,您需要服务器避免返回刷新令牌,因为您的客户端可能无法安全地存储它。它应该发出一个具有上面提到的相同限制的访问令牌。

它的存在是出于安全考虑,而不是为了简单。

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

用户代理是用户(“资源所有者”)与系统其他部分(身份验证服务器和资源服务器)通信的软件。

客户端是在资源服务器上访问用户资源的软件。

在用户代理和客户端分离的情况下,授权代码授予是有意义的。例如,用户使用网络浏览器(user-agent)登录Kickstarter上的Facebook账户。在本例中,客户端是Kickstarter的一个服务器,负责处理用户登录。该服务器从Facebook获取访问令牌和刷新令牌。因此,这种类型的客户端被认为是“安全的”,由于访问受限,令牌可以保存,Kickstarter可以访问用户的资源,甚至在没有用户交互的情况下刷新访问令牌。

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

除了其他答案,还必须认识到,隐式配置文件只允许一个前端通道流,而不是需要回调授权服务器的授权代码流;这在OpenID Connect(一种建立在Auth 2.0之上的SSO协议)中非常明显,其中隐式流类似于非常流行的SAML POST绑定,而授权代码流类似于不太广泛部署的SAML Artifact绑定

我想Will Cain回答了这个问题,他说:“出于同样的原因,客户凭证没有任何好处。(任何客户端都可以尝试使用这个流程。)”还要考虑隐式流的redirect_uri可能是“localhost”——没有从授权服务器对隐式流进行回调。由于无法预先信任客户端,用户必须批准用户声明的发布。

在隐式流程中,如果用户的浏览器被损坏(邪恶的扩展/病毒),那么损坏就可以访问用户的资源,并可以做坏事。

在认证流中,腐败不能,因为它不知道客户端的秘密。

https://www.rfc-editor.org/rfc/rfc6749#page-8

隐式的

隐式授权是一个简化的授权代码流 针对使用脚本在浏览器中实现的客户机进行了优化 语言,如JavaScript。在隐式流中,而不是 向客户端发出授权代码,则向客户端发出授权代码 直接访问令牌(作为资源所有者的结果) 授权)。授予类型是隐式的,因为没有中间类型 颁发凭据(例如授权代码)

.用于获取访问令牌)

当在隐式授权流中发出访问令牌时,
. 0 授权服务器不验证客户端。在一些
在这种情况下,客户端身份可以通过重定向URI
来验证 用于向客户端下发访问令牌。访问令牌可以 向资源所有者或其他具有访问权限的应用程序公开

.资源所有者的user-agent

隐式授权提高了某些
的响应性和效率 客户机(例如实现为浏览器内应用程序的客户机),
因为它减少了获得
所需的往返次数 访问令牌。< / p >

虽然隐式授予被设计为支持不能保护客户端机密的应用程序,包括客户端JavaScript应用程序,但一些提供商正在实现一种替代方案,使用没有客户端机密的授权码。OAuth 2.0 IETF rfc - 6749于2012年发布,目前的建议是2017年的一些最新讨论。

关于IETF OAuth邮件列表的2017年讨论可从以下实现者获得:

点击此处阅读更多信息:

隐式的以前被推荐给没有秘密的客户端,但已经被使用没有秘密的授权代码授权所取代。

...

以前,建议基于浏览器的应用程序使用“隐含”;流,该流立即返回访问令牌,并且没有令牌交换步骤。从最初编写规范开始,行业最佳实践已经更改为建议在没有客户端机密的情况下使用授权代码流。这为创建安全流提供了更多机会,例如使用state参数。参考:Redhat德国电信智能健康IT

从隐式授权转移到没有客户端机密的认证代码也提到了这里的移动应用:

隐式授权允许使用GET授权端点中获取令牌。这意味着授权服务器不必支持CORS。

如果这不是一个问题,并且没有其他与授权服务器不灵活相关的问题(例如,出于某种原因,刷新令牌不是可选的),那么授权代码流是首选的,即使是对于公共客户端,根据近期行业趋势和至少这个(当前)正式汇票的实例

从历史上看,实现隐式流还有其他原因,但目前似乎它们被授权代码授予提供的安全优势所超越,包括:

  • 为机密客户端通过反向通道交付和使用令牌的选项
  • 没有在公共客户端的浏览器历史中公开令牌
  • 在令牌发出之前中断未经授权的流——使用PKCE,用于“各类OAuth客户”;

我刚刚看到一些关于OAuth 2.0的文章。作者指出隐式流背后的原因是JS应用程序在那里的请求非常有限:

如果你想知道为什么隐式类型包含在OAuth 2.0中 解释很简单:同源策略。那时,正面 应用程序不允许向不同的主机发送请求 使用代码获取访问令牌。今天我们有CORS (Cross-Origin) 资源共享)。< / p >

https://medium.com/securing/what-is-going-on-with-oauth-2-0-and-why-you-should-not-use-it-for-authentication-5f47597b2611