在将 IdentityServer4 从 .net 7 升级至 .net 9 时遇到的问题,升级过程中将 System.IdentityModel.Tokens.Jwt 从 6.25.0 升级至 8.9.0,升级后下面的测试失败,完整代码见 JwtRequestAuthorizeTests.cs#L490
var someObj = new { foo = new { bar = "bar" }, baz = "baz" };
var someObjJson = JsonSerializer.Serialize(someObj);
var someArr = new[] { "a", "b", "c" };
var someArrJson = JsonSerializer.Serialize(someArr);
var requestJwt = CreateRequestJwt(
issuer: _client.ClientId,
audience: IdentityServerPipeline.BaseUrl,
credential: new X509SigningCredentials(TestCert.Load()),
claims: new[] {
//...,
new Claim("someObj", someObjJson, Microsoft.IdentityModel.JsonWebTokens.JsonClaimValueTypes.Json),
new Claim("someArr", someArrJson, Microsoft.IdentityModel.JsonWebTokens.JsonClaimValueTypes.JsonArray),
});
var url = _mockPipeline.CreateAuthorizeUrl(
clientId: _client.ClientId,
responseType: "id_token",
extra: Parameters.FromObject(new
{
request = requestJwt
}));
var response = await _mockPipeline.BrowserClient.GetAsync(url);
_mockPipeline.LoginRequest.Should().NotBeNull();
_mockPipeline.LoginRequest.Parameters["someObj"].Should().NotBeNull();
_mockPipeline.LoginRequest.Parameters 中不存在 key 为 someObj 的参数
CreateRequestJwt 对于的实现代码:
string CreateRequestJwt(string issuer, string audience, SigningCredentials credential, Claim[] claims, bool setJwtTyp = false)
{
var handler = new JwtSecurityTokenHandler();
handler.OutboundClaimTypeMap.Clear();
var token = handler.CreateJwtSecurityToken(
issuer: issuer,
audience: audience,
signingCredentials: credential,
subject: Identity.Create("pwd", claims));
if (setJwtTyp)
{
token.Header["typ"] = JwtClaimTypes.JwtTypes.AuthorizationRequest;
}
return handler.WriteToken(token);
}
claims 值转给了 ClaimsIdentity
subject: Identity.Create("pwd", claims));
这是 System.IdentityModel.Tokens.Jwt 7.0 开始引入的一个 breaking change,在 JWT 序列化时会忽略 json 类型的
System.Security.Claims.Claim
github 上的相关 issue: