5

I want to add one role as an array element in JWT token in C#.

{
   "roles": ["Administrator"]
}

Currently, I used this type of code to generate the JWT token claims. This does not help me to create an array type of claim.

string PrivateKey = "string private here";
List<Claim> claims = new List<Claim>();
claims.Add(new Claim("roles", "[Administrator]"));
string tokenString = CreateToken(claims, PrivateKey);

public string CreateToken(List<Claim> claims, string privateRsaKey)
        {
.........................................................
                JwtSecurityToken token = new JwtSecurityToken(
                        Issuer,
                        Audience,
                        claims,
                        now,
                        Expiration,
                        null);

                string payload = token.Payload.SerializeToJson();
                return Jose.JWT.Encode(payload, rsa, Jose.JwsAlgorithm.RS256);

}

Actually I want to add only one array element. I can't do like this. because it adds multiple array elements.

List<Claim> claims = new List<Claim>();
claims.Add(new Claim("roles", "[Administrator]"));
claims.Add(new Claim("roles", "[Administrator]"));

How can I do this?

user3732708
  • 623
  • 1
  • 9
  • 20
  • Possible duplicate of [Add a claim to JWT as an array?](https://stackoverflow.com/questions/27266426/add-a-claim-to-jwt-as-an-array) – d00lar Sep 18 '19 at 05:41
  • I want to add one array element. ( ex: { "roles": "["Administrator"]" } )Because of that, I cannot add one claim repeatedly to create an array. – user3732708 Sep 18 '19 at 05:54
  • you can serialize for example new Claim("APIs", JsonConvert.SerializeObject(cos))); – d00lar Sep 18 '19 at 05:57
  • @d00lar when Serialize id there is key and value on every property like this "user": { "userKey": "batman", "username": "bwayne", "displayName": "Bruce Wayne" }. I don't want a key. Only I want is a value as a arry elemet. – user3732708 Sep 18 '19 at 06:22
  • https://stackoverflow.com/a/39382854/11305308 – d00lar Sep 18 '19 at 06:39
  • 1
    or prepare your array in string 'yourway' - append it many times to get "roles","Administrator,user,authenticated" and then when accesing it split in to array by ',' char and will be ok ;P dirty but ok – d00lar Sep 18 '19 at 06:41
  • you can simply do token.Payload["roles"] = new List { "Administrator" }; – Damith Aug 17 '20 at 10:30

4 Answers4

4

Finally, spending hours I found the answer, I have to change the way of generating claims and encode the jwt token

List < string > roleOptions = new List < string > () {
 "Administrator"
};
var payload = new JwtPayload {
 {
  "roles",
  roleOptions
 }
};

    string key = "eyJjb21wYW5pZXMiOlt7IklkIjoxLCJDb2RlIjoiQzAxIiwiTmFtZSI6IkNvbXBhbnkgSSIsIkJyYW5jaGVzIjpudWxsLCJVc2VycyI6W3siSWQiOjEsIk5hbWUiOiJV";
    var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
    var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
    var header = new JwtHeader(credentials);
    var secToken = new JwtSecurityToken(header, payload);
    var handler = new JwtSecurityTokenHandler();
    var tokenString1 = handler.WriteToken(secToken);
    _logger.Info(secToken.ToString());
    _logger.Info(tokenString1);
user3732708
  • 623
  • 1
  • 9
  • 20
0

This part really helped me:

For adding array as a key we have to make it a list and then add it to jwt payload.

    List < string > roleOptions = new List < string > () { 
      "Administrator"
    };
    var payload = new JwtPayload {
      {
        "roles",
         roleOptions
      }
    };
mohammadAli
  • 375
  • 2
  • 13
0

This is my implementation

contains

  • expiration of token
  • array of roles as List<string>

https://github.com/scholtz/covid-sk-api/blob/main/CovidMassTesting/Model/Token.cs

Note, that usr.Roles must be List<string> and not string[]

        /// <summary>
        /// Method creates jwt token
        /// </summary>
        /// <param name="usr">User object</param>
        /// <param name="configuration">APP Configuran</param>
        /// <returns></returns>
        public static string CreateToken(User usr, IConfiguration configuration)
        {
            if (usr is null)
            {
                throw new ArgumentNullException(nameof(usr));
            }

            if (configuration is null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            var key = Encoding.ASCII.GetBytes(configuration["JWTTokenSecret"]);

            var payload = new JwtPayload {
                  {
                    Token.Claims.Email,
                     usr.Email
                  },{
                    Token.Claims.Name,
                     usr.Name
                  },
                  {
                    Token.Claims.Role,
                     usr.Roles
                  },
                  {
                    "nbf",
                     DateTimeOffset.UtcNow.AddSeconds(-1).ToUnixTimeSeconds()
                  },
                  {
                    "iat",
                     DateTimeOffset.UtcNow.AddSeconds(-1).ToUnixTimeSeconds()
                  },
                  {
                    "exp",
                     DateTimeOffset.UtcNow.AddDays(1).ToUnixTimeSeconds()
                  },
            };

            var credentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature);

            var header = new JwtHeader(credentials);
            var secToken = new JwtSecurityToken(header, payload);
            var handler = new JwtSecurityTokenHandler();
            return handler.WriteToken(secToken);
        }
Scholtz
  • 2,878
  • 2
  • 23
  • 23
0

After so many unsuccessful attempts and trying this for the whole weekend, I could finally fix the problem of converting a singleton array,

using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Newtonsoft.Json;

IList<string> roleList = new List<string>();
roleList.Add("Administrator");

string rolesJson = JsonConvert.SerializeObject(roleList);

claims.Add(new Claim("roles", rolesJson, JsonClaimValueTypes.JsonArray));

var jwt = new JwtSecurityToken(
                issuer: ...,
                audience: ...,
                claims: claims ..);

This serialises the array of values as JSON and adds the claim as JSON Value Type. Hope this will help someone who's struggling with the same.

Cheers!

Nadun Kulatunge
  • 1,567
  • 2
  • 20
  • 28