如何通过 RSA 私钥在 jwt 中设置 kid header 声明?

How to set kid header claim in jwt from RSA private key?

我想生成一个带有“kid”声明的 JWT 令牌 header。我有一个 XML 格式的 RSA 私钥来签署 JWT 令牌。但是在我的 JWT 中,我找不到“kid”header 声明以及类型和算法。我该怎么做?

这里是生成 JWT 令牌的代码:

public async Task<IActionResult> Generate()
{
    var rsa = RSA.Create();
    string key = await System.IO.File.ReadAllTextAsync(options.PrivateKeyFilePath);
    rsa.FromXmlString(key);

    var credentials = new SigningCredentials(new RsaSecurityKey(rsa), SecurityAlgorithms.RsaSha256);

    var jwt = new JwtSecurityToken(
        new JwtHeader(credentials),
        new JwtPayload(
            "webapi",
            "webapi",
            new List<Claim>(),
            DateTime.UtcNow,
            DateTime.UtcNow.AddHours(3)
        )
    );

    string token = new JwtSecurityTokenHandler().WriteToken(jwt);

    return Ok(new { Token = token });
}

这是我的 RSA 私钥。

<RSAKeyValue>
<Modulus>yRfxNTDYqxjEgow6HHBPBEiK6NrVCyLFpG8dklP7f7kFuKZozHopqnly/24Gf6jt9xYLFIsQhhRcuclzEKNnBcWzKlXg9xRwk0o2JzPCh1Ifn1XQ67FrD8+HlBT9DfxjkvzCkPLxi8UWxgifIGauVeFbhIOkVfS0JrIJyQI33sUmiciBGXnO9CjEUpiBcoY53CRa49aUBoKJFDuHV2zuPWCEHLYXrP8Ns15jRU70V/YYUzU3R3PnWk3ZA/12YqtMAJaXFE33DQE71Ccd6HsXfUJpJAM81O/pDPDsk3b3260eN20nLDT0F2acOYQb/3bVKzqZ97isZYqekkmXdeuy4Q==</Modulus>
<Exponent>AQAB</Exponent>
<P>5iuGQcTqCvpwII6EOr1+F98GviZ/PWtHoDkiP8ZiSVCH8XEYCiuPmuWBtOYlv+hLJ9zWUVPkD5uIatLttT6ZxCi7oP+A6htgTbRyLN4NAibwtfQAKQOtue98HyIE6J17OPu8EVBXUSL9rC98OxcbxqDPLOX0geWoIt8BIE9v5js=</P>
<Q>36kW0+j+wHZyx6weriPO5xBAdYBmrd04rSM2hNEZETHMm30JzSYdfU3HATGYiCwexXGlioRMM6xm84DHkWo3Abqaeou2JRFR7PD3UTnsvYBxFxlTd4RfRcNvdvZHFkN4U1sik0FkYbSit6zGU2agEaegp5Jt0vT+CeDonMrUjZM=</Q>
<DP>INPGUy0FgElVop8Q5tvN1xO8/3O4JAdf8M8VPmlJ7VDqAppxpkmuMpZXGHjWm3dC+M17V6ASX9N78lhhBL+H6L0yfXTTaxA6fPqmahXFXzA0lo7VUwQuS92HI12Tu6VyRJ9KpGGEApNuAJfJLRhPotWelrW5WKlrgIWzwGrz968=</DP>
<DQ>A/1PI+6HBMXYHEmsrmyDF0oJ7E6jBjzo8uWq5kmYid76iFd9okQoyIBnqVTKJLusvNbfHg5oEY/ksjk81hIv8v7yHHd7g0PA01ok/zTqTSMKYWAZRgt9a5Al39hawkHn1ozMnBXRhZCkSmRxkTFGb6ouym5pORcXpPN3Erznd7M=</DQ>
<InverseQ>IOdFLHWNtVoAMGAp1wuHWqXIv0BnLnJSce7h+iwm3e165oiszxYa/k/UrMam8qlbjESBZM43oJwGyXtBFVjdTNxyugw5rF04xgrDtMjqb/ZxK1mdoidL15Ij/NZpbd5HtVZ8nzf38wRvMYIzZSA06/V5cYI2molR6gMcWEaClJw=</InverseQ>
<D>N1dzdmP+/PdP/W2CAJmX5WHheLvgrbPgGKTLyp16NWhB/tMtPDjShqvtzgYFm9RtyPY0Dm9HGN85tZePJyERFTGXYStJQjZJ1P8zcA56lqsvMLZ5TKQDBtLiSQqNqe+vp6AQG7wAZarT3aQ5xrz7dX8TpKBl9ZHmkk+lCcCmh5PVZYaRhYTfJp1vONjKKA1L/ivOxKKmjcQnky/A0Po24d8lI5iBLaCco6dThZqvDdfhbudkFnbTDIsb0K/NEqTlC9/XH59CKSUU+jwNY2B1P9MUodmqdi5sce3OIw9sffPcBaSypLiCEH8IvAFyZCWFuxR6zdSBOyQrfu4KNfcNEQ==</D>
</RSAKeyValue>

kid可以设置为SecurityKey.KeyId 属性:

...
var rsaSecurityKey = new RsaSecurityKey(rsa);
rsaSecurityKey.KeyId = "your kid";
var credentials = new SigningCredentials(rsaSecurityKey, SecurityAlgorithms.RsaSha256);
...

有了这个,生成的令牌的第一部分是 Base64url 解码:

{"alg":"RS256","kid":"your kid","typ":"JWT"}