我不知道我是否只是有某种盲点或什么,但我已多次阅读OAuth 2规范并仔细阅读邮件列表档案,我还没有找到一个很好的解释为什么已经开发出用于获得访问令牌的隐式授权流程。与授权代码授予相比,似乎只是放弃了客户端身份验证,没有非常令人信服的理由。这是如何“针对使用脚本语言在浏览器中实现的客户端进行优化”(引用规范)?
两个流程都是相同的(来源:http://tools.ietf.org/html/draft-ietf-oauth-v2-22):
这是流动分裂的地方。在这两种情况下,此时重定向URI都是由客户端托管的某个端点:
因此我的问题是:通过跳过客户端身份验证步骤获得了什么?
答案 0 :(得分:182)
以下是我的想法:
授权代码流中auth代码+令牌的目的是令牌和客户端机密永远不会暴露给资源所有者,因为它们在服务器到服务器之间传播。
另一方面,隐式授权流程适用于完全使用javascript实现且在资源所有者浏览器中运行的客户端。您不需要任何服务器端代码来使用此流程。然后,如果一切都发生在资源所有者的浏览器中,那么发布身份验证代码&客户秘密了,因为令牌&客户端密钥仍将与资源所有者共享。包括身份验证代码和客户端秘密只会使流程更加复杂,而不会增加任何真正的安全性。
所以关于“获得了什么?”的答案是“简单”。
答案 1 :(得分:83)
出于安全原因,这不是为了简单起见。
您应该考虑用户代理与客户之间的区别:
用户代理是用户(“资源所有者”)与系统的其他部分(认证服务器和资源服务器)通信的软件。
客户端是想要访问资源服务器上用户资源的软件。
对于解耦用户代理和客户端,授权代码授予是有意义的。例如。用户使用Web浏览器(用户代理)在Kickstarter上使用他的Facebook帐户登录。在这种情况下,客户端是Kickstarter的服务器之一,它处理用户登录。此服务器从Facebook获取访问令牌和刷新令牌。因此,这种类型的客户端被认为是“安全的”,由于访问受限,可以保存令牌,Kickstarter可以访问用户的资源,甚至无需用户交互即可刷新访问令牌。
如果用户代理和客户端耦合(例如,本机移动应用程序,javascript应用程序),则可以应用隐式授权工作流程。它依赖于资源所有者的存在(用于输入凭据),并且不支持刷新令牌。如果此客户端存储访问令牌供以后使用,则会出现安全问题,因为该令牌可以由其他应用程序或客户端用户轻松提取。缺少刷新令牌是一个额外的提示,该方法不是为在没有用户的情况下访问用户资源而设计的。
答案 2 :(得分:57)
通常的解释是,当您使用JavaScript客户端时,隐式授权更容易实现。但我认为这是错误的观察方式。如果您使用的是直接通过XMLHttpRequest请求受保护资源的JavaScript客户端,则隐式授权是您唯一的选择,尽管它不太安全。*
授权代码授权提供了额外的安全性,但只有在您的Web服务器请求受保护资源时才有效。由于Web服务器可以存储访问令牌,因此访问令牌暴露给Internet的风险较小,您可以发出持续时间较长的令牌。由于Web服务器是可信任的,因此可以为其提供“刷新令牌”,因此当旧服务器到期时它可以获得新的访问令牌。
但是 - 这一点很容易被遗漏 - 授权代码流的安全性只有在Web服务器受到会话保护时才有效,该会话是通过用户身份验证(登录)建立的。如果没有会话,不受信任的用户可以使用client_id向Web服务器发出请求,这与用户拥有访问令牌的情况相同。添加会话意味着只有经过身份验证的用户才能访问受保护的资源。 client_id只是JS webapp的“身份”,而不是对所述webapp的身份验证。
这也意味着您可以在OAuth令牌过期之前结束会话。没有标准方法可以使访问令牌无效。但是如果你的会话到期,访问令牌就没用了,因为除了web服务器之外没有人知道它。如果不受信任的用户获得了对会话密钥的访问权限,则只要会话有效,他们就只能访问受保护的资源。
如果没有Web服务器,则必须使用隐式授权。但这意味着访问令牌暴露给Internet。如果不受信任的用户获得对它的访问权限,他们可以使用它直到它过期。这意味着他们可以访问它的时间比授权代码授权更长。因此,您可能需要考虑尽快使令牌过期,并避免访问更敏感的资源。
* 编辑:最近,人们建议您避免使用隐式授权,即使在没有服务器的网络应用上也是如此。相反,您可以使用配置了空密码的授权代码授权以及PKCE。 auth-code grant避免将访问令牌存储在浏览器历史记录中,如果有人劫持重定向URL以窃取auth代码,PKCE将避免暴露它。在这种情况下,您需要服务器以避免返回刷新令牌,因为您的客户端可能无法安全地存储它。它应该发出一个具有上述相同限制的访问令牌。
答案 3 :(得分:21)
归结为:如果用户正在运行基于浏览器或“公共”(JavaScript)的Web应用程序而没有服务器端组件,则用户隐式信任应用程序(和它运行的浏览器,可能与其他基于浏览器的应用程序...)。
没有第三方远程服务器,只有资源服务器。授权代码没有任何好处,因为除了代表用户的浏览器之外,没有其他代理。出于同样的原因,客户端凭据没有任何好处。 (任何客户端都可以尝试使用此流程。)
然而,安全隐患很重要。来自http://tools.ietf.org/html/rfc6749#section-10.3:
使用隐式授权类型时,将传输访问令牌 URI片段,可以将其暴露给未授权方。
来自http://tools.ietf.org/html/rfc6749#section-10.16:
资源所有者可以自愿委派对资源的访问权限 向攻击者的恶意客户端授予访问令牌。这可能 是由于网络钓鱼或其他一些借口...
答案 4 :(得分:13)
我不确定我是否正确理解答案和Dan的评论。在我看来,答案已经说明了一些事实是正确的,但它确实指出了OP所要求的。如果我理解正确,隐式授权流程的主要优点是像JS应用程序(例如Chrome扩展程序)这样的客户端不必公开客户端密钥。
丹·塔夫林说:...在授权代码流中,资源所有者永远不需要查看访问令牌,而在javascript客户端中这是不可避免的。但是,仍然可以使用授权代码流从javascript客户端保留客户机密码。
也许我误解了你,但是客户端(在这种情况下是JS应用程序)必须将客户端凭证(客户端密钥和密钥)传递给授权代码流中的资源服务器,对吧?客户端密钥不能“保留JS”。
答案 5 :(得分:6)
虽然Implicit Grant旨在支持无法保护客户端密钥的应用程序(包括客户端JavaScript应用程序),但某些提供程序正在使用授权代码实现替代方案而不使用客户端密钥。 OAuth 2.0 IETF RFC-6749于2012年发布,目前的建议最近的讨论是从2017年开始的。
2017年IETF OAuth邮件列表的讨论可从这些实施者处获得:
在这里阅读更多内容:
隐式以前是为没有秘密的客户推荐的,但已经被授权代码授权所取代,并且没有任何机密。
...
以前,建议基于浏览器的应用程序使用“隐式”流程,该流程会立即返回访问令牌,并且没有令牌交换步骤。自规范最初编写以来,行业最佳实践已经改变,建议在没有客户机密的情况下使用授权代码流。这为创建安全流提供了更多机会,例如使用state参数。参考文献:Redhat,Deutsche Telekom,Smart Health IT。
此处的移动应用程序还提到了从隐式授权转移到没有Client Secret的Auth Code:
答案 6 :(得分:3)
除了其他答案之外,同样重要的是要意识到隐式配置文件允许仅前端通道流,而不是需要回调授权服务器的授权代码流;这在OpenID Connect中变得明显,OpenID Connect是一个构建于Auth 2.0之上的SSO协议,其中Implicit流程类似于非常流行的SAML POST绑定,而授权代码流程类似于部署较少的SAML工件绑定
答案 7 :(得分:3)
在隐含流程中,如果用户的浏览器已损坏(恶意扩展/病毒),则损坏可以访问用户的资源,并且可以做坏事。
在auth流程中,腐败无法解决,因为它不知道客户端的秘密。
答案 8 :(得分:1)
我认为Will Cain在他说"出于同样的原因,客户端凭据没有任何好处。 (任何客户都可以尝试使用此流程。)"还要考虑隐式流的redirect_uri可能是" localhost" - 没有从授权服务器对隐式流进行回调。由于无法预先信任客户端,因此用户必须批准发布用户声明。
答案 9 :(得分:1)
https://tools.ietf.org/html/rfc6749#page-8
隐
隐式授权是简化的授权代码流 针对使用脚本在浏览器中实现的客户端进行了优化 JavaScript等语言。在隐式流程中,而不是 向客户端发出授权代码,发出客户端 直接访问令牌(作为资源所有者的结果) 授权)。授权类型是隐式的,因为没有中间 颁发凭证(例如授权代码)(以及稍后 用于获取访问令牌。)
在隐式授权流程期间发出访问令牌时,
授权服务器不对客户端进行身份验证。在某些中 在这种情况下,可以通过重定向URI来验证客户端身份 用于将访问令牌传递给客户端。访问令牌可以 暴露给资源所有者或有权访问的其他应用程序 资源所有者的用户代理。隐性补助提高了一些人的反应能力和效率 客户端(例如作为浏览器内应用程序实现的客户端),
因为它减少了获得一个所需的往返次数 访问令牌。
答案 10 :(得分:0)
隐式授予允许使用php > var_dump($re);
array(2) {
[0]=>
string(4) "@max"
[1]=>
string(5) "Gezim"
}
php > var_dump(array_search('@max', $re) === false);
bool(false)
从Authorization Endpoint获得令牌。这意味着授权服务器不必支持CORS。
如果这不成问题,并且没有其他与授权服务器有关的问题不灵活(例如,出于某些原因,刷新令牌不是可选的),则授权代码流是首选的,即使对于公共客户端, recent industry trends,至少到目前的instance of an official draft。
从历史上看,还有其他原因可以实现隐式流程,但看来授权代码授权所提供的安全优势目前无法解决这些隐患,
答案 11 :(得分:0)
我刚刚遇到了一些有关OAuth 2.0的文章。作者指出,隐式流程背后的原因是JS应用在该请求中受到严格限制:
如果您想知道为什么OAuth 2.0中包含隐式类型, 解释很简单:同源策略。那时,前端 不允许应用程序将请求发送到其他主机 使用代码获取访问令牌。今天我们有CORS(Cross-Origin 资源共享)。