question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Single-item-claim-array when using ClaimValueTypes.Json changing schema

See original GitHub issue

Hi folks,

Please see the previous two issues I filed eventually routing me here by the AspNetCore folks:

IdentityServer/IdentityServer4#3968 https://github.com/dotnet/aspnetcore/issues/18178

When sending over a JWT with an array claim with only one value, the claim in user.profile gets transformed to just a string. When an array with 2 values gets sent over in the JWT claim, user.profile sets it to an array with those 2 values.

This means that the schema changes depending on how many items are in the claim which is less than ideal and forces some special casing.

To Reproduce

Consider this code applied to a React + ASP.NET template with Individual User authentication/authorization. The snippet has IdentityServer send over the JWT claim as an array even if it only has one value in it:

public Task GetProfileDataAsync(ProfileDataRequestContext context)
{
    // Get all the roles associated with this subject
    IEnumerable<Claim> roleClaims = context.Subject.FindAll(JwtClaimTypes.Role);

    // Put those roles into a list so we can serialize them after
    IList<string> roles = new List<string>();
    foreach (Claim roleClaim in roleClaims)
    {
        Debug.Assert(roleClaim.Type == JwtClaimTypes.Role);

        roles.Add(roleClaim.Value);
    }

    // Serialize the roles into JSON
    string rolesJson = JsonSerializer.Serialize(roles);

    // Put the roles JSON into an actual Claim object
    Claim claim = new Claim(JwtClaimTypes.Role, rolesJson, IdentityServerConstants.ClaimValueTypes.Json);

    // Add the claim to the IssuedClaims which will eventually end up in the issued JWT
    context.IssuedClaims.Add(claim);

    return Task.CompletedTask;
}

The JWT that comes out on the other end does have an array with 1 value in it but user.profile transforms it into a string.

If you don’t want to actually create a role before testing this, just replace rolesJson above with "[\"role1\"]".

From AuthorizeServices.js checking out user.profile where the claims end up on the client side:

image

image

I considered this as a bug because it overrides the explicitly defined preference of IdentityServer.

Further technical details

  • ASP.NET Core version 3.1

.NET Core SDK (reflecting any global.json): Version: 3.1.100
Commit: cd82f021f4

Runtime Environment:
OS Name: Windows
OS Version: 10.0.18362 OS Platform: Windows RID: win10-x64 Base Path: C:\Program Files\dotnet\sdk\3.1.100\

Host (useful for support): Version: 3.1.0 Commit: 65f04fb6db

.NET Core SDKs installed: 3.0.100 [C:\Program Files\dotnet\sdk] 3.1.100 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed: Microsoft.AspNetCore.All 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] Microsoft.AspNetCore.App 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.AspNetCore.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.NETCore.App 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.WindowsDesktop.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

To install additional .NET Core runtimes or SDKs: https://aka.ms/dotnet-download

  • The VSCode 1.41.1

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:7 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
a7md0commented, Aug 2, 2022

@a7md0, did you find a workaround for this?

@NickDarvey Yes, see this Stackoverflow answer

For reference my code was

claims.AddClaims(userRoles.Select(role => new Claim("roles", role)));

Changed to

claims.AddClaim(new Claim("roles", JsonSerializer.Serialize(userRoles), JsonClaimValueTypes.JsonArray));
0reactions
NickDarveycommented, Aug 1, 2022

@a7md0, did you find a workaround for this?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Single-item-claim-array when using ClaimValueTypes. ...
Single-item-claim-array when using ClaimValueTypes.Json still changing schema #3968. azydevelopment opened this issue on Jan 6, 2020 · 5 ...
Read more >
Dataframes reading json files with changing schema
We are using the following logic to read json - first we read the base schema which has all fields and then read...
Read more >
JSON Schema Serializer and Deserializer
This document describes how to use JSON Schema with the Apache Kafka® Java client and console tools. The Confluent Schema Registry based JSON...
Read more >
How to Validate Your JSON Using JSON Schema
The schema can be defined in a JSON file, and be loaded into your code or it can be directly created in the...
Read more >
How to Use JSON Schema to Validate JSON Documents in ...
A JSON Schema is a valid JSON document with key/value pairs. Each key has a special meaning and is used to define the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found