Add a claim to JWT as an array?

后端 未结 4 1018
醉话见心
醉话见心 2021-01-01 17:52

Using thinktecture JWT authentication resource owner flow,i use the claims part of JWT for client consumption. My question is that if its possible to add claim in identity s

相关标签:
4条回答
  • 2021-01-01 18:11

    use JsonClaimValueTypes as claim type

    var tokenDescriptor = new SecurityTokenDescriptor
       {
        Subject = new ClaimsIdentity(new Claim[]
         { new Claim("listName", list != null ? JsonSerializer.Serialize(user.RoleName) : string.Empty,JsonClaimValueTypes.JsonArray)
        }}
    
    0 讨论(0)
  • 2021-01-01 18:12

    I was having a similar issue, in my case I have claims that are arrays but sometimes only have one item depending on user permissions. In that case if you use new Claim("key", "value") to add them they will be strings when there is a single object and arrays when > 1 which was unacceptable.

    A better solution in this case is to use JwtPayload to build the JwtSecurityToken object.

    var payload = new JwtPayload
        {
            { "ver", version },
            { "iss", "example.com"},
            { "iat", DateTimeOffset.UtcNow.ToUnixTimeSeconds()},
            { "exp", DateTimeOffset.UtcNow.AddHours(1).ToUnixTimeSeconds()},
            { "aud", myExampleStringList }
        };
    var token = new JwtSecurityToken(new JwtHeader(_signingCredentials), payload);
    

    This works on .netcore 3.0 using System.IdentityModel.Tokens.Jwt v3.0 but I can't confirm for other versions.

    0 讨论(0)
  • 2021-01-01 18:13

    Speaking from personal experience, it is easier to inter-op with claim stores when the ValueType is always type "String". Although it may seem counter intuitive when you know you are dealing with a complex type, it is at least simple to understand.

    The way I have approached this need for an array is to have my application code expect multiple claims to be present for the claim type in question, and keep each claim value of a simple type.

    Examp:

    var authorizeCompanies = identity.FindAll(AuthorizedCompanies).Select(c => c.Value);
    

    And of course, you also add them that way:

    identity.AddClaim(ClaimTypes.Name, response.UserName);
    identity.AddClaim(AuthorizedCompanies, "CompanyX");
    identity.AddClaim(AuthorizedCompanies, "CompanyY");
    identity.AddClaim(AuthorizedCompanies, "CompanyZ");
    

    IdentityServer supports this model out of the box. When generating a token for an identity such as this, it automatically writes the values for that claim out as an array.

    {
        "aud": "Identity Server example/resources", 
        "iss": "Identity Server example", 
        "exp": 1417718816, 
        "sub": "1234",
        "scope": ["read", "write"], // <-- HERE
        "foo": ["bar", "baz"],      // <-- HERE TOO!
        "nbf": 1417632416
    }
    

    This approach to claims is in contrast to assuming all claims are a one-to-one mapping of type -> value.

    0 讨论(0)
  • 2021-01-01 18:35

    Identity Server will convert the value from an array to string if you want to add a single value to an array. An easier solution would be to convert the array as json and add to the claim with valueType as json.

    IList<string> companies = new List<string>();
    companies.Add("CompanyA");
    string companiesJson = JsonConvert.SerializeObject(companies);
    context.IssuedClaims.Add(new Claim("Companies", companiesJson, IdentityServerConstants.ClaimValueTypes.Json));
    

    The above solution will allow you to add one or more values to claim as an array.

    0 讨论(0)
提交回复
热议问题