317

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

然而,使用“授权码”流程,客户端(通常是 Web 服务器)只有在资源所有者(即用户)授予访问权限后才能获得授权码。然后,客户端使用该授权代码再次调用 API,将 client_id 和 client_secret 与授权代码一起传递以获取访问令牌。一切都在这里描述得很好

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

问题:当“隐式”流接缝很好时,为什么还要打扰“授权码”流?为什么不对网络服务器也使用“隐式”?

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

4

8 回答 8

351

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

OAuth 2.0 希望满足这两个标准:

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

详情如下:

由于安全原因,隐式流仅在浏览器环境中是可能的:

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

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

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

隐式流程还存在安全问题,需要进一步的逻辑来解决/避免,例如:

  • 攻击者可以从不同网站/应用程序上的用户获取访问令牌(假设他是另一个网站/应用程序的所有者),在他们的网站上记录令牌,然后将其作为 URL 参数传递到您的网站因此在您的网站上冒充用户。为避免这种情况,您需要检查与访问令牌关联的客户端 ID(例如,对于 Google,您可以使用 tokeninfo 端点)以确保令牌是使用您自己的客户端 ID(即由您自己的应用程序)颁发的或检查签名如果您使用的是 IDToken(但这需要您的客户端密码)。
  • 如果身份验证请求不是来自您自己的财产(称为会话固定攻击),为避免这种情况,您需要从您的网站生成随机散列,将其保存在 cookie 中并在状态 URL 参数中传递相同的散列身份验证请求,当用户回来时,您使用 cookie 检查状态参数,它必须匹配。

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

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

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

于 2012-11-14T23:41:47.690 回答
14

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

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

于 2016-10-02T17:44:04.630 回答
7

对于 Google 员工:

  • 您将 Gmail 联系人的访问权限授予第 3 方
  • 以令牌的形式授予访问权限
  • 任何拥有有效令牌的人都将获得访问权限
  • 所以你不想暴露代币,并尽量减少它的转移
  • 通过隐式流程,(不受控制的)浏览器获取访问令牌,从而将令牌公开
  • 使用身份验证代码流,浏览器只会获得临时身份验证代码,但不会获得访问令牌,身份验证代码也无用,没有只有第 3 方和 Gmail 知道的秘密

结论

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

隐喻

  • 隐式流程:您向 PROVIDER 索要密钥,您将其存放在您的钱包中,您负责保管它,您直接小心使用密钥,并及时将其换成新密钥
  • 验证码流程:您要求一个代码,代码被交给您的代客,您的代客将代码和一个秘密文本结合起来,然后与提供者交换一个密钥,您要求您的代客在需要时使用密钥,但永远不会看到密钥你自己,你的代客负责交换新的钥匙
  • 大多数时候,您的代客比您更具有安全意识 :)
  • 当您没有代客泊车时,您只能靠自己
于 2020-09-08T10:19:04.670 回答
5

OAuth 规范

4.2. 隐式授权

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

由于这是一个基于重定向的流程,客户端必须能够与资源所有者的用户代理(通常是 Web 浏览器)进行交互,并且能够接收来自授权服务器的传入请求(通过重定向)。

与授权码授予类型不同,在这种授权类型中,客户端分别发出授权请求和访问令牌请求,客户端接收访问令牌作为授权请求的结果。

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

所以我们可以考虑:

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

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

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

因此我认为我们应该引入一个新的“安全隐式”授权流程,它严格在 https 上工作,允许刷新令牌(或者我们应该完全摆脱它们),并且比 Auth Cose 授权流程更可取

于 2018-04-24T08:44:34.153 回答
5

对我们来说,我们的客户希望能够在他们的手机上使用我们的应用程序进行一次身份验证,而不必一次重新登录数周。使用代码流,您将获得一个刷新令牌以及您的访问令牌。隐式流程不会为您提供刷新令牌。访问令牌的有效期相对较短,但刷新令牌的有效期最长为 90 天。每当访问令牌过期时,客户端和服务器代码都可以使用该刷新令牌来获取新的访问令牌和刷新令牌,所有这些都在后台进行,无需任何用户干预。刷新令牌只能使用一次。你不能用隐式流来做到这一点。如果您使用的是隐式流程,并且您的用户超过一个小时没有与您的应用程序交互,那么当他们回来时,他们将不得不再次登录。这在我们的用例中是不可接受的,

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

代码流很棒,但确实需要更多的工作。MS 目前没有 Angular 库来处理它,所以我不得不写一个。如果你有兴趣,我可以帮你。

于 2020-01-13T17:57:26.830 回答
3

我的回答是:你不能用 web-app 服务器以安全简单的方式实现隐式流。

Web 应用授权过程涉及用户交互,因此身份验证服务器应在用户身份验证和同意后将用户的浏览器重定向回 Web 应用的目标页面(在与认证服务器)。

所以应该使用重定向 URL 将令牌传递给 web-app,对吗?

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

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

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

于 2019-07-29T21:54:39.007 回答
2

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

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

注意 - 根据oauth 最佳实践,“客户端不应使用隐式授权(响应类型“令牌”)或其他响应类型在授权响应中发布访问令牌”。

希望这可以帮助。

于 2020-08-06T07:26:51.030 回答
0

谈到授权代码授予类型,我们通过删除对客户端(用户代理或网站)的最终资源的特权访问来获得更高的安全性,其中客户端(网站所有者)使用您的授权假装是您代码,以及避免黑客在您的浏览器上使用 XSS(网站漏洞)进行 CRSF,如果使用隐式方法可能会发生这种情况。

关键成分是客户端 ID,它出现在向 Auth 服务器发出的第一个请求中。您可以将 Auth Code 步骤视为签名验证。

此外,即使完成了获取访问令牌的授权代码步骤,最终,access_token 最终还是在客户端手中。那时,验证服务器不再需要客户端 ID 来进行签名验证。因此,我不确定授权代码方法是否也完全安全(来自客户端本身)。这就是为什么即使在提供登录凭据后,身份验证服务器也会要求您同意的原因。这意味着您使用访问令牌信任客户端。

于 2021-11-21T14:28:51.693 回答