当“隐式”流程运行良好时,为什么OAuth2中存在“授权代码”流程?

时间:2012-11-14 21:32:00

标签: authentication oauth oauth-2.0

使用“隐式”流程后,客户端(可能是浏览器)将在资源所有者(即用户)提供访问权限后获得访问令牌。

然而,使用“授权代码”流程,客户端(通常是Web服务器)仅在资源所有者(即用户)授予访问权限后才获得授权代码。使用该授权代码,客户端再次调用API,将client_id和client_secret与授权代码一起传递,以获取访问令牌。 All well described here

两个流都具有完全相同的结果:访问令牌。但是,“隐式”流程要简单得多。

问题:为什么要打扰“授权代码”流程,当“隐式”流程接缝没问题?为什么不对网络服务器使用“隐式”?

这对提供商和客户来说都是更多的工作。

7 个答案:

答案 0 :(得分:238)

tl; dr:这完全是出于安全原因。

OAuth 2.0希望满足以下两个标准:

  1. 您希望允许开发人员使用非HTTPS重定向URI,因为并非所有开发人员都具有启用SSL的服务器,如果他们这样做,则并非总是正确配置(非自签名,可信SSL证书,同步服务器时钟......)
  2. 您不希望黑客通过拦截请求来窃取访问/刷新令牌。
  3. 以下详细信息:

    由于安全原因,隐式流只能在浏览器环境中使用:

    隐式流中,访问令牌直接作为哈希片段(而不是URL参数)传递。关于散列片段的一个重要的事情是,一旦你遵循包含散列片段的链接,只有浏览器知道散列片段。浏览器会将哈希片段直接传递到目标网页(重定向URI /客户端的网页)。散列片段具有以下属性:

    • 它们不是HTTP请求的一部分,因此服务器无法读取它们,因此它们不能被中间服务器/路由器拦截(这很重要)。
    • 它们只存在于浏览器 - 客户端 - 所以读取哈希片段的唯一方法是使用在页面上运行的JavaScript。

    这使得可以将访问令牌直接传递给客户端,而不存在被中间服务器拦截的风险。这有一个警告,只有可能是客户端,需要运行客户端的javascript才能使用访问令牌。

    授权代码流中,无法直接在URL参数中传递访问令牌,因为URL参数是HTTP请求的一部分,因此您的请求所依赖的任何中间服务器/路由器如果你没有使用加密连接(HTTPS)允许所谓的中间人攻击,那么pass(可能是数百个)就能够读取访问令牌。

    理论上可以直接在URL参数中传递访问令牌,但是auth服务器必须确保重定向URI使用带有TLS加密的HTTPS和“可信”SSL证书(通常来自证书颁发机构,即不是免费的)确保目标服务器是合法的,并且HTTP请求是完全加密的。让所有开发人员购买SSL证书并在其域上正确配置SSL将是一个巨大的痛苦,并将大大减缓采用速度。这就是为什么提供中间一次性使用“授权代码”,只有合法的接收者能够交换(因为你需要客户端密码),并且该代码对潜在的黑客通过未加密的交易拦截请求是无用的(因为他们不知道客户的秘密)。

    你也可以争辩说隐式流程的安全性较低,有一些潜在的攻击媒介,例如在重定向时欺骗域名 - 例如通过劫持客户端网站的IP地址。这就是为什么隐式流只授予访问权限(它应该具有有限的时间使用)并且从不刷新令牌(其在时间上是无限制的)的原因之一。为解决此问题,我建议您尽可能在支持HTTPS的服务器上托管您的网页。

答案 1 :(得分:7)

隐式流程使整个流程非常简单,但安全性也降低了 由于客户端应用程序(通常是在浏览器中运行的JavaScript)不太受信任,因此不会返回用于长期访问的刷新令牌。
对于需要临时访问(几个小时)用户数据的应用程序,您应该使用此流程 将访问令牌返回给JavaScript客户端也意味着您的基于浏览器的应用程序需要特别小心 - 想想可能将访问令牌泄漏到其他系统的XSS攻击。

https://labs.hybris.com/2012/06/05/oauth2-the-implicit-flow-aka-as-the-client-side-flow

答案 2 :(得分:5)

对于我们来说,我们的客户希望能够一次在手机上通过我们的应用进行身份验证,而不必一次连续数周再次登录。通过代码流,您将获得刷新令牌以及访问令牌。隐式流程不会为您提供刷新令牌。访问令牌的有效期相对较短,但刷新令牌的有效期最多为90天。每当访问令牌过期时,客户端和服务器代码都可以使用该刷新令牌在后台获取新的访问令牌和刷新令牌,而无需任何用户干预。刷新令牌只能使用一次。您不能使用隐式流执行此操作。如果您使用的是Implicit Flow,并且您的用户在一个多小时内未与您的应用进行交互,则他们必须在再次访问时再次登录。在我们的用例中这是不可接受的,并且Code Flow安全地支持我们的用例。

这有效且安全,因为可以撤消刷新令牌。如果客户说他们丢失了手机,笔记本电脑或黑客进入了台式机,我们可以简单地撤销该用户的所有刷新令牌。在整个过程中,没有任何个人身份信息(PII)触及我们的代码-即用户的密码。

代码流很棒,但是确实需要更多工作。 MS目前没有Angular库来处理它,因此我不得不编写一个。如果您有兴趣,我可以为您提供帮助。

答案 3 :(得分:1)

来自OAuth spec的第4.2段:

隐式授权类型用于获取访问令牌(它不支持刷新令牌的发布),并针对已知操作特定重定向URI的公共客户端进行了优化。这些客户端通常使用脚本语言(如JavaScript)在浏览器中实现。

作为基于重定向的流,客户端必须能够与资源所有者的用户代理(通常是Web浏览器)交互,并且能够从授权服务器接收传入请求(通过重定向)。 / p>

与客户端单独发出授权和访问令牌请求的授权代码授予类型不同,客户端会根据授权请求接收访问令牌。

隐式授权类型不包括客户端身份验证,并且依赖于资源所有者的存在和重定向URI的注册。由于访问令牌被编码到重定向URI中,因此可能会将其暴露给资源所有者和驻留在同一设备上的其他应用程序。

那么我们可以得到什么结论:

  1. 这适用于公共OAuth,即客户不需要注册且没有自己的客户机密。但是auth服务器检查重定向URL是什么,这实际上足以保证安全。

  2. Access令牌出现在浏览器的地址栏中,因此用户可以复制该URL并发送给其他人,并且它也会以用户身份登录,即类似会话固定。但是浏览器通过替换历史记录进行额外的重定向以从URL中删除哈希片段。 黑客还可以通过嗅探HTTP流量来窃取访问令牌,但这可以通过HTTPS轻松保护。 某些恶意浏览器扩展可以从地址栏访问URL,但这最终是糟糕的情况,比如破坏的HTTPS证书。甚至Auth代码流也无法帮助以太。 所以我可以看到,通过url的哈希片段传递访问令牌是绝对安全的。

  3. 使用HTTPS时,临时访问令牌和刷新令牌的分离是无用的,说实话,即使在原始HTTP上也没那么有用。 但是客户端通过隐式流程无法接收刷新令牌这一事实也是无稽之谈。

  4. 因此,我认为我们应该引入一个新的授权流程“safe implicit”,它严格地通过https工作,允许刷新令牌(或者我们应该完全摆脱它们),并且优于Auth Cose授权流程

答案 4 :(得分:1)

在“隐式”流程中,客户端(可能是浏览器)将通过浏览器重定向(GET操作)获得访问令牌。基于浏览器的通信并不安全,您的客户机密或令牌可能会被拦截或被盗。

在“授权码”流程中,客户端(通常是Web服务器)仅通过浏览器重定向(GET操作)仅获取授权码。然后,服务器通过对授权服务器进行(非浏览器)POST调用来与令牌交换此代码。服务器仅包含用于令牌访问呼叫的客户端机密。

注意-根据oauth best practices,“客户端不应使用隐式授权(响应类型为“令牌”)或其他发出访问权限的响应类型 授权响应中添加令牌”。

希望这会有所帮助。

答案 5 :(得分:1)

对于Google员工:

  • 您向第三方授予对Gmail联系人的访问权限
  • 以令牌形式授予访问权限
  • 具有有效令牌的任何人都将获得访问权限
  • 因此您不想公开令牌,并尽量减少其转移
  • 通过隐式流程,(不受控制的)浏览器将获取访问令牌,从而将该令牌公开。
  • 使用身份验证代码流,浏览器仅会获得临时身份验证代码,而不会获得访问令牌,并且,如果没有第3方和Gmail知道的秘密,该身份验证代码将毫无用处

结论

  • 要使攻击者能够访问您的Gmail联系人,它必须侵入您的第三方帐户
  • 但是,攻击者永远无法获得访问令牌,因此无法直接对您的Gmail联系人进行操作
  • 您可能授权第三者访问许多服务,因此您不想将所有重要令牌存储在本地计算机上
  • 但是,在一种情况下,您只能使用隐式流程:当第3方在本地运行并且没有后端来存储令牌时
  • 然后,它只能依靠前端来存储令牌,它几乎没有控制权

隐喻

  • 隐性流程:您要求提供者提供密钥,将其存储在钱包中,有责任确保密钥的安全,您应谨慎使用密钥,并及时更换新密钥
  • 验证码流程:您要求输入密码,代码已交给您的VALET,您的VALET将代码和秘密文本结合在一起,然后将其与PROVIDER交换为密钥,您要求VALET在需要时使用该密钥,但永远不要自己看到钥匙,您的VALET负责交换新钥匙
  • 大多数时候,您的VALET比您更了解安全性:)
  • 没有VALET时,您自己一个人

答案 6 :(得分:0)

我的答案是:您不能使用Web应用服务器以安全,简单的方式实现隐式流。

Web应用程序授权过程涉及用户交互,因此,身份验证服务器应在用户进行身份验证和同意后,将用户的浏览器重定向回到Web应用程序的目标页面(我看不到任何其他方式来传递用户与Authentication Server进行一些交互后,返回到Web应用。

因此应该使用重定向URL将令牌传递到Web应用程序,对吧?

@NicolasGarnier在其回答和评论中解释说,没有办法将令牌作为URL片段传递-它不会到达网络应用服务器。

即使在HTTPS下,将令牌作为重定向URL的URL参数传递也是不安全的:如果目标页面(让它为“ greetings page”)包含资源(图像,脚本等),则该资源将由浏览器获取一系列HTTP(S)请求(每个请求都有Referer HTTP标头,其中包含“问候页面”的确切URL,包括URL参数)。这是令牌泄漏的方式。

因此,似乎没有办法在重定向URL中传递令牌。这就是为什么您需要第二次调用(从身份验证服务器到客户端(但指向哪个URL?)或从客户端到身份验证服务器(在授权代码流中的第二次调用))