Search code examples
c#propertiesjwtclaims

Why does JwtSecurityToken fail to include the claims properties in JwtToken?


I'm trying to include additional properties in my claims.

However when I pass the claims through new JwtSecurityToken() the properties are not included in the JwtSecurityToken

This is the code generating the claims with properties:

                    foreach(var appRole in userDetails.ApplicationRoles)
                    {
                        var claim = new Claim(ClaimTypes.Role, appRole.AppRole.Code);
                        claim.Properties.Add("Scope", "Application");
                        claim.Properties.Add("Foo", "Bar");
                        claims.Add(claim);
                    }

This is the code generating the JWToken:

        public string CreateToken(IEnumerable<Claim> claims, DateTime expiresAt)
        {
            var secretKey = Encoding.ASCII.GetBytes(Configuration.GetValue<string>("SecurityKey"));
            var issuer = Configuration.GetValue<string>("Issuer");
            var audience = Configuration.GetValue<string>("Audience");
            var Jwt = new JwtSecurityToken(
                issuer: issuer,
                audience: audience,
                claims: claims,
                notBefore: DateTime.UtcNow,
                expires: expiresAt,
                signingCredentials: new SigningCredentials(
                    new SymmetricSecurityKey(secretKey),
                    SecurityAlgorithms.HmacSha256Signature));
            return new JwtSecurityTokenHandler().WriteToken(Jwt);
        }

The Jwt token has all the claims listed, but the claims with additional properties don't have the properties populated.


Solution

  • Claims are key-value pairs, so they do not have additional properties. Still, the value of a claim can have any type so it can be an object or an array. In your case, you could create an array of objects that each has the code, scope, and foo fields, then add the whole array, for example, to a roles claim. Alternatively, you could create multiple claims, where each claim name would be prefixed with the role value. However, this approach will be more complicated for consumers, I think.

    (I'm not that confident with writing C# code so I'm not posting any)