IdentityServer / IdentityServer4

OpenID Connect and OAuth 2.0 Framework for ASP.NET Core
https://identityserver.io
Apache License 2.0
9.23k stars 4.01k forks source link

TokenExtensions.CreateJwtPayload wraps JSON objects in JObject which is not serializable correctly #5385

Closed trejjam closed 1 year ago

trejjam commented 2 years ago

Try to create JwtToken with Claim(type: "json", value: Dictionary<string, int>{["foo"] = 1}) with at least one scope. The result is JWT with claim without original meaning.

The real cause of this is started here: https://github.com/IdentityServer/IdentityServer4/blob/3ff3b46698f48f164ab1b54d124125d63439f9d0/src/IdentityServer4/src/Extensions/TokenExtensions.cs#L92

And misusage later here: https://github.com/IdentityServer/IdentityServer4/blob/3ff3b46698f48f164ab1b54d124125d63439f9d0/src/IdentityServer4/src/Extensions/TokenExtensions.cs#L103...L112

A live example of the wrong serialization is here: https://dotnetfiddle.net/uOd8QS


An example in the IdentityServer scope

Source claim:

new Claim("json-claim", JsonConvert.SerializeObject(new Dictionary<string, int>{["foo"] = 1}), "json")

Expected JWT token:

{
...
  "scope": [
    "api",
    "offline_access"
  ],
  "json-claim": {
    "foo": 1
  }
}

Produced JWT token:

{
...
  "scope": [
    "api",
    "offline_access"
  ],
  "json-claim": {
    "foo": []
  }
}

It is caused by the Microsoft.IdentityModel.Json.Serialization.DefaultContractResolver._contractCache which maps JValue of the directory to a previously serialized array (scope).


I think the solution is to pass deserialized Json instead of JRaw.Parse result. At least it works in my custom TokenCreationService.

leastprivilege commented 2 years ago

Important update

This organization is not maintained anymore besides critical security bugfixes (if feasible). This organization will be archived when .NET Core 3.1 end of support is reached (3rd Dec 2022). All new development is happening in the new Duende Software organization.

The new Duende IdentityServer comes with a commercial license but is free for dev/testing/personal projects and companies or individuals making less than 1M USD gross annnual revenue. Please get in touch with us if you have any question.