Home > OS >  String Claim Types Error when JWT Decoding?
String Claim Types Error when JWT Decoding?

Time:12-12

When I do Login operation, JWT token is returning as a response. However, when I decode with JS, I am getting this:

{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

I want to be like

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

What could be the reason? .Net Core 3.1 React with TypeScript

I create token by 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));
     }

 }

I use SigningCredentials as SecurityAlgorithms.HmacSha256Signature

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

finally I decoded token with JwtDecode librar const decodedToken = jwtDecode(response.data.token)

CodePudding user response:

The problem is that OpenIDConnect/OAuth and Microsoft have different opinions on what the claim names should be and by default .NET will rename some of the claims behind the scene.

To stop this, you need to turn of the claims mapping using:

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

Then you need tell .NET what the name of the name/role claim should be, by setting this:

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

For more details about claims mapping visit:

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

  • Related