JWT解码时字符串声明类型错误?

String Claim Types Error when JWT Decoding?

当我执行登录操作时,JWT 令牌作为响应返回。但是,当我用 JS 解码时,我得到这个:

{http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: '1', http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: 'RESMAK ', http://schemas.microsoft.com/ws/2008/06/identity/claims/role: 'Administrator', FirmNumber: '1', PeriodNumber: '1', …}
FirmNumber: "1"
PeriodNumber: "1"
aud: "Audience"
exp: 1639301639
http://schemas.microsoft.com/ws/2008/06/identity/claims/role: "Administrator"
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: "RESMAK "
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: "1"
iss: "Issuer"
nbf: 1639215239
[[Prototype]]: Object

我想成为

FirmNumber: "1"
PeriodNumber: "1"
aud: "Audience"
exp: 1639301639
role: "Administrator"
name: "RESMAK "
nameidentifier: "1"
iss: "Issuer"

可能是什么原因? .Net Core 3.1 与 TypeScript 反应

我通过 JwtHelper 创建令牌 Class


public class JwtHelper
 {
     public IConfiguration Configuration { get; }
     private TokenOptions _tokenOptions;
     private DateTime _accessTokenExpiration;

     public JwtHelper(IConfiguration configuration)
     {
         Configuration = configuration;
         _tokenOptions = Configuration.GetSection("TokenOptions").Get<TokenOptions>();
     }
     public AccessToken CreateToken(User user, List<OperationClaim> operationClaims, UserForLoginDto userForLoginDto)
     {
         _accessTokenExpiration = DateTime.Now.AddMinutes(_tokenOptions.AccessTokenExpiration);
         var securityKey = SecurityKeyHelper.CreateSecurityKey(_tokenOptions.SecurityKey);
         var signingCredentials = SigningCredentialsHelper.CreateSigningCredentials(securityKey);
         var jwt = CreateJwtSecurityToken(_tokenOptions, user, operationClaims, userForLoginDto, signingCredentials);
         var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
         var token = jwtSecurityTokenHandler.WriteToken(jwt);

         return new AccessToken
         {
             Token = token,
             Expration = _accessTokenExpiration
         };
     }

     //securityKey ,signingCredentials ve diger token optionsdan gelen bilgileri toplayarak bir JwtToken Üretiyoruz.
     public JwtSecurityToken CreateJwtSecurityToken(TokenOptions tokenOptions, User user, List<OperationClaim> operationClaims, UserForLoginDto userForLoginDto, SigningCredentials signingCredentials)
     {
         var jwt = new JwtSecurityToken
         (
            issuer: tokenOptions.Issuer,
            audience: tokenOptions.Audience,
            expires: _accessTokenExpiration,
            notBefore: DateTime.Now,
            claims: SetClaims(user, operationClaims, userForLoginDto),
            signingCredentials: signingCredentials
         );
         return jwt;
     }

     private IEnumerable<Claim> SetClaims(User user, List<OperationClaim> operationClaims, UserForLoginDto userForLoginDto)
     {
         var claims = new List<Claim>();
         claims.AddNameIdentifier(user.Id.ToString());
         claims.AddName($"{user.FirstName} {user.LastName}");
         claims.AddRoles(operationClaims.Select(x => x.Name).ToArray());
         claims.AddFirmNumber(userForLoginDto.FirmNumber.ToString());
         claims.AddPeriodNumber(userForLoginDto.PeriodNumber.ToString());
         return claims;
     }
 }


public static class ClaimExtensions
 {

     public const string ClaimTypeFirmNumber = "FirmNumber";
     public const string ClaimTypePeriodNumber = "PeriodNumber";


     public static void AddName(this ICollection<Claim> claims, string name)
     {
         claims.Add(new Claim(ClaimTypes.Name, name));
     }
     public static void AddNameIdentifier(this ICollection<Claim> claims, string nameIdentifier)
     {
         claims.Add(new Claim(ClaimTypes.NameIdentifier, nameIdentifier));
     }
     public static void AddRoles(this ICollection<Claim> claims, string[] roles)
     {
         foreach (var role in roles)
         {
             claims.Add(new Claim(ClaimTypes.Role, role));
         }

     }
     public static void AddPeriodNumber(this ICollection<Claim> claims, string periodNumber)
     {
         claims.Add(new Claim(ClaimTypePeriodNumber, periodNumber));
     }
     public static void AddFirmNumber(this ICollection<Claim> claims, string firmNumber)
     {
         claims.Add(new Claim(ClaimTypeFirmNumber, firmNumber));
     }

 }

我使用 SigningCredentials 作为 SecurityAlgorithms.HmacSha256Signature

  public class SigningCredentialsHelper
    {
        public static SigningCredentials CreateSigningCredentials(SecurityKey securityKey)
        {
            return new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);//GEnellikle bu şifreleme algoritması kullanılır
        }
    }

最后我用 JwtDecode 库解码了令牌 const decodedToken = jwtDecode(response.data.token)

问题是 OpenIDConnect/OAuth 和 Microsoft 对于声明名称应该是什么有不同的意见,默认情况下 .NET 会在幕后重命名一些声明。

要停止此操作,您需要使用以下方法关闭声明映射:

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.Clear();

然后你需要告诉 .NET name/role 声明的名称应该是什么,通过设置:

opt.TokenValidationParameters.RoleClaimType = "roles";
opt.TokenValidationParameters.NameClaimType = "name";

有关声明映射的更多详细信息,请访问:

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/claims?view=aspnetcore-6.0