8. Authorization Server-Provided Nonce (授权服务器提供的 Nonce)
8. Authorization Server-Provided Nonce (授权服务器提供的 Nonce)
本节规定了一种机制,使用服务器提供的不透明 nonce 来限制 DPoP 证明的生命周期。如果不采用这种机制,控制客户端的恶意方(可能包括最终用户)可以创建在未来任意时间使用的 DPoP 证明。
授权服务器可以使用 DPoP 证明中包含的由其提供的 nonce 值来限制 DPoP 证明的生命周期。服务器决定何时发出新的 DPoP nonce 质询以及是否需要,从而要求在后续的 DPoP 证明中使用该 nonce 值。服务器做出该决定的逻辑超出了本文档的范围。
授权服务器可以提供一个 nonce 值,由客户端包含在发送的 DPoP 证明中。在这种情况下,授权服务器根据 [RFC6749] 第 5.2 节对不包含 nonce 的请求响应 HTTP 400 (Bad Request) 错误响应,使用 use_dpop_nonce 作为错误代码值。授权服务器在响应中包含 DPoP-Nonce HTTP 头部,提供在发送后续请求时使用的 nonce 值。Nonce 值必须是不可预测的。当由于 nonce 不匹配而提供新的 nonce 值时,也使用此相同的错误代码。客户端通常会在收到带有随附 nonce 值的 use_dpop_nonce 错误后,使用提供的新 nonce 值重试请求。
例如,当授权服务器需要 nonce 时,在响应没有 nonce 的令牌请求时,授权服务器可以响应如下 DPoP-Nonce 值,以提供要包含在 DPoP 证明中的 nonce 值:
HTTP/1.1 400 Bad Request
DPoP-Nonce: eyJ7S_zG.eyJH0-Z.HX4w-7v
{
"error": "use_dpop_nonce",
"error_description":
"Authorization server requires nonce in DPoP proof"
}
图 20: 对没有 Nonce 的令牌请求的 HTTP 400 响应
错误响应中也可以包含其他 HTTP 头部和 JSON 字段,但不得有多个 DPoP-Nonce 头部。
收到 nonce 后,预计客户端将使用 DPoP 证明重试其令牌请求,该 DPoP 证明在 nonce 声明中包含提供的 nonce 值。包含 nonce 的此类 DPoP 证明的未编码 JWT 有效负载示例如下所示。
{
"jti": "-BwC3ESc6acc2lTc",
"htm": "POST",
"htu": "https://server.example.com/token",
"iat": 1562262616,
"nonce": "eyJ7S_zG.eyJH0-Z.HX4w-7v"
}
图 21: 包含 Nonce 值的 DPoP 证明有效负载
Nonce 对客户端是不透明的。
如果 DPoP 证明中的 nonce 声明与授权服务器最近提供给客户端的 nonce 不完全匹配,则授权服务器必须拒绝该请求。拒绝响应可以包含 DPoP-Nonce HTTP 头部,提供用于后续请求的新 nonce 值。
其意图是客户端只需要保留一个 nonce 值,服务器只需要保留一个最近 nonce 的窗口。也就是说,可能会出现临时情况,即服务器和客户端存储的 nonce 值不同。但是,这种情况是可以自我纠正的。对于任何拒绝消息,服务器可以向客户端发送它希望客户端使用的 nonce 值,客户端可以存储该 nonce 值并用其重试请求。即使客户端和/或服务器丢弃了其存储的 nonce 值,这种情况也是可以自我纠正的,因为在响应失败的请求或重试失败的请求时可以传达新的 nonce 值。
请注意,默认情况下,使用 CORS [WHATWG.Fetch] 的基于浏览器的客户端应用程序只能访问 CORS 安全列表响应 HTTP 头部。为了使应用程序获得并使用 DPoP-Nonce HTTP 响应头值,服务器需要通过在 Access-Control-Expose-Headers 响应头列表值中包含 DPoP-Nonce 使其可供应用程序使用。
8.1. Nonce 语法
[RFC6749] 使用的 ABNF 中的 nonce 语法(与 scope-token 语法相同)如下所示。
nonce = 1*NQCHAR
图 22: Nonce ABNF
8.2. 提供新的 Nonce 值
由授权服务器决定何时提供供客户端使用的新 nonce 值。预计客户端将在 DPoP 证明中使用现有的已提供 nonce,直到服务器提供新的 nonce 值。
授权服务器可以以提供初始 nonce 的相同方式提供新的 nonce:在响应中使用 DPoP-Nonce HTTP 头部。DPoP-Nonce HTTP 头字段使用第 8.1 节中定义的 nonce 语法。每次发生这种情况时,都需要额外的协议往返。
还定义了一种提供新 nonce 值的更有效方式,即在前一个请求的 HTTP 200 (OK) 响应中包含 DPoP-Nonce HTTP 头部。客户端必须将提供的新 nonce 值用于下一个令牌请求以及所有后续令牌请求,直到授权服务器提供新的 nonce。
包含 DPoP-Nonce HTTP 头部的响应应该是不可缓存的(例如,在响应 GET 请求时使用 Cache-Control: no-store),以防止响应被用于服务后续请求,并因此导致使用过时的 nonce 值。
下面显示了提供新 nonce 值的示例 200 OK 响应。
HTTP/1.1 200 OK
Cache-Control: no-store
DPoP-Nonce: eyJ7S_zG.eyJbYu3.xQmBj-1
图 23: 提供下一个 Nonce 值的 HTTP 200 响应