我不知道我是否只是有某种盲点或什么,但我已多次阅读OAuth 2规范并仔细阅读邮件列表档案,我还没有找到一个很好的解释为什么隐含格兰特已经开发出用于获得访问令牌的流程 . 与授权代码授权相比,似乎只是放弃了客户端身份验证,没有非常令人信服的理由 . 这是如何“针对使用脚本语言在浏览器中实现的客户端进行优化”(引用规范)?
两个流都开始相同(来源:http://tools.ietf.org/html/draft-ietf-oauth-v2-22):
-
客户端通过将资源所有者的用户代理指向授权 endpoints 来启动流 .
-
授权服务器对资源所有者进行身份验证(通过用户代理),并确定资源所有者是否授予或拒绝客户端的访问请求 .
-
假设资源所有者授予访问权限,授权服务器使用前面提供的重定向URI(在请求中或在客户端注册期间)将用户代理重定向回客户端 .
-
重定向URI包含授权代码(授权代码流)
-
重定向URI包含URI片段中的访问令牌(隐式流)
这是流动分裂的地方 . 在这两种情况下,此时重定向URI都是由客户端托管的某个 endpoints :
-
在授权代码流中,当用户代理使用URI中的授权代码命中该 endpoints 时,该 endpoints 上的代码会将授权代码及其客户端凭据交换为访问令牌,然后可以根据需要使用该令牌 . 例如,它可以将其写入页面上的脚本可以访问的网页中 .
-
隐式流完全跳过此客户端身份验证步骤,只是加载带有客户端脚本的网页 . 这里有一个可爱的技巧,URL片段可以防止访问令牌过多传递,但最终结果基本相同:客户端托管的站点提供一个页面,其中包含一些可以获取访问令牌的脚本 .
因此我的问题是:通过跳过客户端身份验证步骤获得了什么?
11 回答
以下是我的想法:
授权代码流中的auth代码令牌的目的是令牌和客户端机密永远不会暴露给资源所有者,因为它们在服务器到服务器之间传播 .
另一方面,隐式授权流程适用于完全使用javascript实现且在资源所有者的浏览器中运行的客户端 . 您不需要任何服务器端代码来使用此流程 . 然后,如果一切都在资源所有者的浏览器中发生,那么再发出身份验证代码和客户端密钥是没有意义的,因为令牌和客户端密钥仍将与资源所有者共享 . 包括身份验证代码和客户端密钥只会使流程更复杂,而不会增加任何真正的安全性 .
所以答案是“已经获得了什么?”是“简单” .
It's there for security reasons, not for simplicity.
您应该考虑 user agent 和 client 之间的区别:
用户代理是用户(“资源所有者”)与系统的其他部分(认证服务器和资源服务器)通信的软件 .
客户端是想要访问资源服务器上的用户资源的软件 .
在解耦用户代理和客户端的情况下, Authorization Code Grant 是有意义的 . 例如 . 用户使用Web浏览器(用户代理)在Kickstarter上使用他的Facebook帐户登录 . 在这种情况下,客户端是Kickstarter 's servers, which handles the user logins. This server gets the access token and the refresh token from Facebook. Thus this type of client considered to be 717262 , due to restricted access, the tokens can be saved and Kickstarter can access the users'资源之一,甚至在没有用户交互的情况下刷新访问令牌 .
如果用户代理和客户端耦合(例如,本机移动应用程序,javascript应用程序),则可以应用 Implicit Authorization Workflow . 它依赖于资源所有者的存在(用于输入凭据),并且不支持刷新令牌 . 如果此客户端存储访问令牌供以后使用,则会出现安全问题,因为该令牌可以由客户端的其他应用程序或用户轻松提取 . 缺少刷新令牌是一个额外的提示,该方法不是为在没有用户的情况下访问用户资源而设计的 .
通常的解释是,当您使用JavaScript客户端时,隐式授权更容易实现 . 但我认为这是错误的看法 . 如果您使用的是直接通过XMLHttpRequest请求受保护资源的JavaScript客户端,则隐式授权是您唯一的选择,尽管它不太安全 .
授权代码授予提供了额外的安全性,但只有在Web服务器请求受保护资源时才有效 . 由于Web服务器可以存储访问令牌,因此访问令牌暴露给Internet的风险较小,您可以发出持续很长时间的令牌 . 由于Web服务器是可信任的,因此可以为其提供“刷新令牌”,因此可以获得新的访问权限当旧的到期时令牌 .
但是 - 这一点很容易被遗漏 - 授权代码流的安全性只有在Web服务器受到会话保护时才有效,该会话是通过用户身份验证(登录) Build 的 . 如果没有会话,不受信任的用户可以使用client_id向Web服务器发出请求,这与用户拥有访问令牌的情况相同 . 添加会话意味着只有经过身份验证的用户才能访问受保护的资源 . client_id只是JS webapp的“身份”,而不是所述webapp的身份验证 .
这也意味着您可以在OAuth令牌过期之前结束会话 . 没有标准的方法来使访问令牌无效 . 但是如果你的会话到期,访问令牌就没用了,因为除了web服务器之外没有人知道它 . 如果不受信任的用户获得了对会话密钥的访问权限,则只要会话有效,他们就只能访问受保护的资源 .
如果没有Web服务器,则必须使用隐式授权 . 但这意味着访问令牌暴露给Internet . 如果不受信任的用户获得对它的访问权限,他们可以使用它直到它过期 . 这意味着他们可以访问它的时间比授权代码授权更长 . 因此,您可能需要考虑尽快使令牌过期,并避免访问更敏感的资源 .
它归结为:如果用户正在运行基于浏览器或没有服务器端组件的"public"(JavaScript)Web应用程序,则用户会隐式信任该应用程序(以及运行它的浏览器,可能还有其他基于浏览器的应用程序)应用...) .
没有第三方远程服务器,只有资源服务器 . 授权代码没有任何好处,因为除了代表用户的浏览器之外,没有其他代理 . 出于同样的原因,客户端凭据没有任何好处 . (任何客户端都可以尝试使用此流程 . )
然而,安全隐患很重要 . 来自http://tools.ietf.org/html/rfc6749#section-10.3:
来自http://tools.ietf.org/html/rfc6749#section-10.16:
我不确定我是否正确理解答案和Dan的评论 . 在我看来,答案已经说明了一些事实是正确的,但它确实指出了OP所要求的 . 如果我理解正确,隐式授权流程的主要优点是像JS应用程序(例如Chrome扩展程序)这样的客户端不必公开客户端密钥 .
丹塔夫林说:
也许我误解了你,但客户端(在这种情况下是JS应用程序)必须将客户端凭证(客户端密钥和机密)传递给授权代码流中的资源服务器,对吧?客户端密钥不能“保留JS” .
虽然Implicit Grant旨在支持无法保护客户端密钥的应用程序,包括客户端JavaScript应用程序,但某些提供商正在使用授权代码而不使用客户端密钥来实现替代方案 . OAuth 2.0 IETF RFC-6749于2012年发布,目前的建议是最近的一些讨论来自2017年 .
这些实施者可以在2017年讨论IETF OAuth邮件列表:
Redhat:https://www.ietf.org/.../oauth/current/msg16966.html
Deutsche Telekom:https://www.ietf.org/.../oauth/current/msg16968.html
智能 Health IT:https://www.ietf.org/.../oauth/current/msg16967.html
在这里阅读更多:
https://aaronparecki.com/oauth-2-simplified/
https://aaronparecki.com/oauth-2-simplified/#single-page-apps
移动应用程序还提到了从隐式授权转移到没有Client Secret的Auth Code:
除了其他答案之外,同样重要的是要认识到Implicit配置文件允许仅前端通道流,而不是需要回调授权服务器的授权代码流;这在OpenID Connect中变得明显,OpenID Connect是一个构建在Auth 2.0之上的SSO协议,其中Implicit流类似于非常流行的SAML POST绑定,而授权代码流类似于不太广泛部署的SAML工件捆绑
在隐式流程中,如果用户的浏览器已损坏(恶意扩展/病毒),则损坏可以访问用户的资源并可以执行不良操作 .
在auth流程中,腐败不能,因为它不知道客户机密钥 .
我认为Will Cain在回答这个问题时说:“由于同样的原因,客户端凭据没有任何好处 . (任何客户端都可以尝试使用此流程 . )”还要考虑隐式流的redirect_uri可能是“localhost” - 没有回调是由授权服务器为隐式流程 . 由于无法预先信任客户端,因此用户必须批准发布用户声明 .
https://tools.ietf.org/html/rfc6749#page-8
隐式授权允许从Authorization Endpoint获得具有
GET
的令牌 . 这意味着授权服务器不必支持CORS .如果这不是一个问题,并且没有其他与授权服务器相关的问题不灵活(例如刷新令牌由于某种原因不是可选的)那么授权代码流是首选,即使对于公共客户端,根据recent industry trends和至少这个(当前)instance of an official draft .
从历史上看,还有其他原因可以实现隐式流程,但似乎授权代码授予提供的安全优势目前超过了它们,包括:
选项通过反向通道为机密客户端提供和使用令牌
不在公共客户端的浏览器历史记录中公开令牌
在令牌发出之前中断未经授权的流程 - 使用PKCE,用于"all kinds of OAuth clients"