出示持有证明( DPoP )

DPoP 通过提供公私钥对的持有证明,该机制允许客户端获取受发件人限制的 OAuth 令牌。

该规范目前处于草案阶段: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-dpop-11

DPoP HTTP 页眉

DPoP 标头是一个带签名的JWT,其中包含用于证明持有权的关键信息。

DPoP JWT 的 JOSE 标头必须至少包含以下参数:

参数 描述
typ JWT 的类型。 该值必须为“dpop+jwt”。
ALG 签名算法。 有效值包括: RS256、 RS384、 RS512、 PS256、 PS384、 PS512、 ES256、 ES384、 ES512
JWK 一个表示公钥的 JSON Web Key (JWK)。 不得包含私钥。

JOSE 标头示例:

{
  "typ": "dpop+jwt",
  "alg": "RS256",
  "jwk": {
    "kty": "RSA",
    "n": "...",
    "e": "AQAB"
  }
}

DPoP JWT 的有效负载必须至少包含以下声明:

声明名称 描述
jti 此 JWT 的唯一标识符。
htm 附加了 JWT 的请求的 ` HTTP ` 方法。
htu HTTP 目标 URI,不包含查询字符串和片段部分。 这应该是“推送授权请求”(PAR)端点或令牌端点。
iat JWT 的创建时间戳。

JWT 有效负载示例:

{
  "jti": "3765f59c-43cd-4cf8-8180-73bc9ae4ff3c",
  "htm": "POST",
  "htu": "https://<tenant-hostname>/oauth2/token",
  "iat": 1661847227
}

DPoP 格式的JWT必须使用私钥进行签名,且该签名必须能够通过JWT的JOSE标头中提供的公钥进行验证。 JWT 的有效期不得超过 30 分钟。 如果没有 exp 声明,则该 JWT 的过期时间默认为在 iat. 中指定的创建时间戳之后 30 分钟。

JWT 通过名为 DPoP. 的标头发送。

请求示例:


curl -ki https://<tenantId>/oauth2/token
 -H "DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6Il..."
 -d "grant_type=client_credentials&client_secret=<secret>&client_id=<clientId>"

Authorize request

授权请求中包含 JSON Web Key 的指纹,该指纹位于查询参数或 POST 请求体中。

参数 描述
dpop_jkt 与该授权请求关联的 JSON Web Key 的指纹。
https://<tenantId>/oauth2/authorize?grant_type=authorization_code&client_id=<clientId>&redirect_uri=<redirect_uri>&dpop_jkt=<dpop_jkt>&...

为此请求生成的授权码将与该指纹绑定,并在请求令牌时用于验证。 这可以防止授权码被盗用,避免在将授权码兑换为代币时,被其他不具备相同私钥的实体用于签署代币请求。

建议结合使用推送式授权请求(PAR)请求对象与 DPoP, ,以安全的方式发送指纹 dpop_jktdpop_jkt此外,在使用 PAR 时,可以使用 ` DPoP ` 头部代替。 详情请参见 DPoP HTTP header 上文。 在配置 OpenID Connect应用程序时,可通过选择 Require pushed authorization request (PAR) 来强制执行推送的授权请求。

代币请求

访问令牌和刷新令牌请求必须包含 DPoP HTTP 头部。 详情请参见 DPoP HTTP header 上文。

对于授权码流程,此 JWK 的指纹必须与授权请求期间发送的 JWK 指纹 (dpop_jkt) 匹配。

请求示例:


curl -ki https://<tenantId>/oauth2/token
 -H "DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6Il..."
 -d "grant_type=client_credentials&client_secret=<secret>&client_id=<clientId>"

执行此流程的结果是一组与持有证明绑定的代币。 这可以通过令牌内省来验证。

令牌内省

对 DPoP 访问令牌进行内省时,会返回额外的声明。
  • DPoPbearertoken_type: 该值应为 ,而非。
  • cnf: JWK 拇指印验证方法会返回公钥的哈希值。
客户端在检查令牌时,应通过将公钥的哈希值与检查响应中的声明 cnfjkt 进行比对,来验证访问令牌的 DPoP 绑定。

内省响应示例:


{
    ...,
    "cnf": {
        "jkt": "yrFAH18WFPml9e9IIo6rB_fLdFX1pdbMgIcd_fW_4aM="
    },
    "token_type": "DPoP",
    ...
}