Skip to content

OidcIdToken cannot be serialized to JSON if token contains claim of type JSONArray #9210

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mengelbrecht opened this issue Nov 20, 2020 · 8 comments
Labels
in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) status: backported An issue that has been backported to maintenance branches type: bug A general bug
Milestone

Comments

@mengelbrecht
Copy link
Contributor

mengelbrecht commented Nov 20, 2020

Describe the bug
If an IdP sends an ID token with claim amr, the Jackson ObjectMapper with SecurityJackson2Modules cannot serialize the ID token to JSON (related: #4370).
The amr claim in the ID token has the type com.nimbusds.jose.shaded.json.JSONArray for which there is no default mixin.

Tested with Spring-Security 5.4.1.

To Reproduce
These steps resemble a normal oauth2Login configuration where additionally the ID token is serialized to JSON.

  1. Include an amr claim in the ID token
  2. Decode the string token value using an JwtDecoder created by OidcIdTokenDecoderFactory to a Jwt.
  3. Create an OidcIdToken from the Jwt.
  4. Serialize the OidcIdToken to a JSON string using an ObjectMapper with the SecurityJackson2Modules.

Expected behavior
The amr claim should be an ArrayList instead of JSONArray.

Workaround
Define a mixin for the JSONArray class.

@mengelbrecht mengelbrecht added status: waiting-for-triage An issue we've not yet triaged type: bug A general bug labels Nov 20, 2020
@mengelbrecht mengelbrecht changed the title OidcIdToken cannot be converted to JSON if token contains claim of type JSONArray OidcIdToken cannot be serialized to JSON if token contains claim of type JSONArray Nov 20, 2020
@jgrandja
Copy link
Contributor

Thanks for the report @mengelbrecht. The default converter for the amr claim is Collection<String> in OidcIdTokenDecoderFactory.createDefaultClaimTypeConverters().

Can you put together a test that reproduces the issue as I'm not seeing how the amr claim is decoded as a com.nimbusds.jose.shaded.json.JSONArray.

@jgrandja jgrandja added in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) status: waiting-for-feedback We need additional information before we can continue and removed status: waiting-for-triage An issue we've not yet triaged type: bug A general bug labels Nov 23, 2020
@jgrandja jgrandja self-assigned this Nov 23, 2020
@mengelbrecht
Copy link
Contributor Author

I could not create a test because the JWT has to be signed and the validator wants to fetch the jwks which fails in my test.

After a little more digging I could reproduce it using this Kotlin snippet. The code outputs com.nimbusds.jose.shaded.json.JSONArray as type for the converted object.

    val jsonArray = com.nimbusds.jose.shaded.json.JSONArray().apply { add("test") }
    val converted = ClaimConversionService.getSharedInstance().convert(
        jsonArray,
        TypeDescriptor.valueOf(Any::class.java),
        TypeDescriptor.collection(Collection::class.java, TypeDescriptor.valueOf(String::class.java))
    )
    println(converted.javaClass.name)

When NimbusJwtProcessor processes the parsed JWT the JWTClaimsSet contains the JSONArray for the amr claim:

JWTClaimsSet jwtClaimsSet = this.jwtProcessor.process(parsedJwt, null);

Just as you mentioned the ObjectToListStringConverter then tries to convert it to a Collection<String> here:

Map<String, Object> claims = this.claimSetConverter.convert(jwtClaimsSet.getClaims());

However, since JSONArray subclasses List<Object> and the first element is of type String the converter decides that there is nothing to do and just returns the source which then still is a JSONArray:

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Nov 23, 2020
@jgrandja
Copy link
Contributor

jgrandja commented Nov 23, 2020

Good catch @mengelbrecht !

So the issue is in ObjectToListStringConverter:

Instead of returning the source as-is, it should instead convert to a new ArrayList<String>().

Would you be interested in submitting this fix?

@jgrandja jgrandja added type: bug A general bug and removed status: feedback-provided Feedback has been provided labels Nov 23, 2020
@jgrandja jgrandja added this to the 5.5.0-M2 milestone Nov 23, 2020
@mengelbrecht
Copy link
Contributor Author

@jgrandja unfortunately I don't have the time at the moment, sorry

@jgrandja
Copy link
Contributor

No worries @mengelbrecht. Thanks for reporting this!

@ghost
Copy link

ghost commented Nov 24, 2020

hi @jgrandja . I have some spare time and I can submit a PR for this today or tomorrow.

@jgrandja
Copy link
Contributor

That would be great @ovidiupopa91. Thank you!

@jgrandja jgrandja assigned ghost and unassigned jgrandja Nov 24, 2020
@jgrandja
Copy link
Contributor

jgrandja commented Nov 24, 2020

@ovidiupopa91 Looks like we could run into the same problem with ObjectToMapStringObjectConverter:

It returns the Map as-is, which could be a com.nimbusds.jose.shaded.json.JSONObject. Could you also update this to return a new Map, as part of the PR. Thanks!

ghost pushed a commit to ovidiupopa07/spring-security that referenced this issue Dec 3, 2020
…ype JSONArray or JSONObject

ObjectToListStringConverter and ObjectToMapStringObjectConverter were checking if the source object is of type List or Map and if the first element or key is a String. If we have a JSONArray containing Strings the above check will pass, meaning that a JSONArray will be returned which is not serializable (same applies to JSONObject)

With this change, even if the check is passing a new List or Map will be returned.

Closes spring-projectsgh-9210
@spring-projects-issues spring-projects-issues added status: backported An issue that has been backported to maintenance branches and removed for: backport-to-5.4.x labels Dec 3, 2020
jgrandja pushed a commit that referenced this issue Dec 3, 2020
…ype JSONArray or JSONObject

ObjectToListStringConverter and ObjectToMapStringObjectConverter were checking if the source object is of type List or Map and if the first element or key is a String. If we have a JSONArray containing Strings the above check will pass, meaning that a JSONArray will be returned which is not serializable (same applies to JSONObject)

With this change, even if the check is passing a new List or Map will be returned.

Closes gh-9210
jgrandja pushed a commit that referenced this issue Dec 3, 2020
…ype JSONArray or JSONObject

ObjectToListStringConverter and ObjectToMapStringObjectConverter were checking if the source object is of type List or Map and if the first element or key is a String. If we have a JSONArray containing Strings the above check will pass, meaning that a JSONArray will be returned which is not serializable (same applies to JSONObject)

With this change, even if the check is passing a new List or Map will be returned.

Closes gh-9210
jgrandja pushed a commit that referenced this issue Dec 3, 2020
…ype JSONArray or JSONObject

ObjectToListStringConverter and ObjectToMapStringObjectConverter were checking if the source object is of type List or Map and if the first element or key is a String. If we have a JSONArray containing Strings the above check will pass, meaning that a JSONArray will be returned which is not serializable (same applies to JSONObject)

With this change, even if the check is passing a new List or Map will be returned.

Closes gh-9210
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) status: backported An issue that has been backported to maintenance branches type: bug A general bug
Projects
None yet
3 participants