为什么 OAuth RFC 要求再次传递 redirect_uri 以交换代码换令牌?

Why does OAuth RFC require the redirect_uri to be passed again to exchange code for token?

假设我的重定向 uri 和授权代码请求是有效的,并且我想用有效代码交换令牌,验证我在 access_code 请求中传递的重定向 URI 匹配相同的好处是什么授权码请求中提供的uri?

防止攻击者操纵Authentication Request,使Authorization Server将code发送到攻击者控制下的URL

如果只有一个向授权服务器注册的重定向 URI(最佳实践)但使用松散类型的匹配时,这种攻击是不可能的 - 例如接受特定域上的任何重定向 URI - 那么攻击者很可能会操纵该域的某些部分(例如,通过开放重定向、易受攻击的 wiki、论坛等)来获取 code 并随后针对合法客户端重播它。有了强制重定向 URI,授权服务器在授权请求中看到的重定向 URI 与客户端用于令牌端点的重定向 URI 之间现在将不匹配。如果根本没有预先注册重定向 URI,这种攻击就更加微不足道了。

这里的推理是规范安全考虑的一部分:https://www.rfc-editor.org/rfc/rfc6749#section-10.6

When requesting authorization using the authorization code grant
type, the client can specify a redirection URI via the "redirect_uri" parameter. If an attacker can manipulate the value of the
redirection URI, it can cause the authorization server to redirect
the resource owner user-agent to a URI under the control of the
attacker with the authorization code.

An attacker can create an account at a legitimate client and initiate the authorization flow. When the attacker's user-agent is sent to the authorization server to grant access, the attacker grabs the authorization URI provided by the legitimate client and replaces the

client's redirection URI with a URI under the control of the
attacker. The attacker then tricks the victim into following the
manipulated link to authorize access to the legitimate client.

Once at the authorization server, the victim is prompted with a
normal, valid request on behalf of a legitimate and trusted client,
and authorizes the request. The victim is then redirected to an
endpoint under the control of the attacker with the authorization
code. The attacker completes the authorization flow by sending the
authorization code to the client using the original redirection URI
provided by the client. The client exchanges the authorization code
with an access token and links it to the attacker's client account,
which can now gain access to the protected resources authorized by
the victim (via the client).

In order to prevent such an attack, the authorization server MUST
ensure that the redirection URI used to obtain the authorization code is identical to the redirection URI provided when exchanging the
authorization code for an access token. The authorization server
MUST require public clients and SHOULD require confidential clients
to register their redirection URIs. If a redirection URI is provided in the request, the authorization server MUST validate it against the registered value.

从我对规范的阅读来看,Hans Z. 的回答似乎是正确的。 https://www.rfc-editor.org/rfc/rfc6749。我会尝试对相同内容进行另一种解释。

首先,来自第 4.1 节的验证码流程:

 +----------+
 | Resource |
 |   Owner  |
 |          |
 +----------+
      ^
      |
     (B)
 +----|-----+          Client Identifier      +---------------+
 |         -+----(A)-- & Redirection URI ---->|               |
 |  User-   |                                 | Authorization |
 |  Agent  -+----(B)-- User authenticates --->|     Server    |
 |          |                                 |               |
 |         -+----(C)-- Authorization Code ---<|               |
 +-|----|---+                                 +---------------+
   |    |                                         ^      v
  (A)' (C)'                                       |      |
   |    |                                         |      |
   ^    v                                         |      |
 +---------+                                      |      |
 |         |>---(D)-- Authorization Code ---------'      |
 |  Client |          & Redirection URI                  |
 |         |                                             |
 |         |<---(E)----- Access Token -------------------'
 +---------+       (w/ Optional Refresh Token)

Note: The lines illustrating steps (A), (B), and (C) are broken into two parts as they pass through the user-agent.

                 Figure 3: Authorization Code Flow

问题是为什么步骤 (D) 需要重定向 URI。

谁拥有什么:

  • 授权服务器归公司 1 所有
  • 客户端由公司 2 所有,使用公司 1 的身份验证基础设施访问资源所有者。

我的假设:

  • (D) 公司 1 和公司 2 之间是安全的(通过某种方式,可能是 client_secret 和 TLS。确切的机制在 RFC 中未定义)
  • 客户端不是公司 1 专门列入白名单的资源。这是 RFC 建议,但不是要求。

恶意客户公司 3 想要以公司 2 为幌子访问资源所有者。

  1. 公司 3 将自己 (BadClient) 作为用户代理和客户公司 2 客户端之间的中间人插入。
  2. 虚假重定向 URI 指向 BadClient Company 3 并显示虚假页面。这些页面诱使用户通过公司 1 为公司 2(client_id 是 Client2)进行身份验证,公司 3 由于伪造的重定向 (C) 而成功接收到身份验证代码。用户认为 Company3 创建的虚假页面实际上属于 Company2。
  3. 恶意客户端从 BadClient 向客户端发出 (C)' 请求,因为它已代表用户收到授权码。例如,www.company2client.com?code=\&state=,尝试获取只有公司 2 应该有权访问的 accessToken。客户端 Company2 将请求连同其 client_secret(只有公司 2 知道)及其 redirect_url(问题是为什么?)一起转发到 Auth 服务器,并将访问令牌返回到(E ) 然后传回恶意客户端中间人。游戏结束。
  4. 为了阻止这种攻击,授权服务器可以比较 (A) 和 (D) 之间的重定向 URL。授权请求 (BadClient) 的 redirect_url 与 access_token 请求(客户端)中提供的 redirect_url 不匹配。请注意,拥有 redirect_urls 的注册白名单可以解决授权请求 (A) 中的这个问题,但这只是 RFC 的建议,不是必须的。相反,RFC 声明在 (D) 中提供 redirect_url 是必须的,而不是强制白名单。

如 user892703 在最后一点所述。如果授权步骤使用客户端在其注册阶段注册的白名单 uri 验证重定向 uri,则在令牌获取步骤中不需要重新发送 redirect_uri。