Search code examples
c#identityserver4

Why does my code think a value is Microsoft.IdentityModel.Json.Linq.JObject when it is actually supposed to be Newtonsoft.Json.Linq.JObject?


I am having a lot of difficulty with a failing unit test. Specifically,

JwtRequestAuthorizeTests.authorize_should_accept_complex_objects_in_request_object()

The test attempts to add an Object parameter to the Claims array, and it is failing because after the request goes through the pipeline, an expected parameter called "someObj" is missing.

For the record, someObj is simply a json object defined as:

{{
    "foo": {
        "bar": "bar"
    },
    "baz": "baz"
}}

Also for the record, when I pull the latest IdentityServer code from GitHub the test passes.

I've discovered that the reason it's failing is because in the method JwtRequestValidator.ProcessPayloadAsync(JwtSecurityToken token), the variable value is of a type different than what's expected. Specifically, the code thinks it's Microsoft.IdentityModel.Json.Linq.JObject when it should be Newtonsoft.Json.Linq.JObject. I can't for the life of me figure out how or why this is the case.

I've included this image to show you that I'm not crazy (or at least, why I don't think I'm crazy). You can see that the cast from value to JObject fails, as jobj = null, and you can also see that value.GetType() returns Microsoft.IdentityModel.Json.Linq.JObject.

enter image description here

So can StackOverflow please tell me why this is happening, and perhaps how I can fix it?

Also, I think it's worth noting that I'm referencing Newtonsoft.Json as it should be:

enter image description here


Solution

  • After migrating from .Netframework WebAPI to dotnetcore3.1, I ran into the exact same issue. I can't believe I searched all over the internet, and was only able to find this question as the only related result.

    Apparently JWT payload type is no longer NewtonSoft.Json.Linq.JObject. It is Microsoft.IdentityModel.Json.Linq.JObject now and is inaccessible outside of its namespace.

    My guess is Microsoft has changed the definition and didn't expect people to use the type outside of its namespace.

    What I ended up doing is getting rid of the type check, and just parse directly in a try{} catch{} block. parse-payload-directly

    Hope this will help someone else in the future.