我有一个使用 JWT 身份验证的 ASP.NET Core API。设置简单:
....
string authority = $"https://{configuration["Auth:Authority"]}";
string audience = configuration["Auth:Audience"];
return builder.AddJwtBearer(options =>
{
options.Authority = authority;
options.Audience = audience;
options.TokenValidationParameters = new TokenValidationParameters
{
// NameClaimType = "http://schemas.org/email"
// NameClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/email"
// NameClaimType = "sub"
};
});
(正如您所看到的注释代码,我一直在尝试几种设置)
当我解码 JWT(使用 jwt.io)时,我看到 JWT 中有声明“sub”并且具有字符串值(dbo 中用户的内部 ID)
{
"nbf": 1592585433,
"exp": 1592585763,
"iss": "https://*************",
"aud": "api_10",
"sub": "142",
"scope": [
"openid",
"api_10"
]
}
问题是 dotnet 将 sub 切换到名称声明。这不会返回 (0) 个结果:
principal.Claims.Where(w => w.Type == "sub")
这返回 userId 我需要“142”:
principal.Claims.Where(w => w.Type == ClaimTypes.Name || ClaimTypes.NameIdentifier)
这是怎么回事?!我的子索赔哪里去了?
只需在 API 的
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
方法上添加 ConfigureServices
即可。它也在其他评论中建议。我在我的示例存储库上验证了它。
此问题是因为 OIDC StandardClaims 在 JWT 令牌处理程序上重命名。通过添加
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
,您将清除 JWT 令牌处理程序上的入站声明类型映射。
阅读更多这里
在 .NET 8 中,您只需将
MapInboundOptions
的 JwtBearerOptions
字段设置为 false
。
例如:
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(o => {
o.MapInboundClaims = false;
…
}