Certain OPs mix usage of boolean and string for boolean type OIDC claims. For example, the same "email_verified" field is presented as boolean in IdToken, but is a string of "true" in the response of user info. This inconsistency results in failures when we try to merge them during authorization. This PR introduce a small leniency so that it will merge a boolean with a string that has value of the boolean's string representation. In another word, it will merge true with "true", also will merge false with "false", but nothing else.
This commit is contained in:
parent
4180333bbc
commit
2e71d0aa91
|
@ -670,8 +670,15 @@ public class OpenIdConnectAuthenticator {
|
|||
} else if (value1 instanceof JSONObject) {
|
||||
idToken.put(entry.getKey(), mergeObjects((JSONObject) value1, value2));
|
||||
} else if (value1.getClass().equals(value2.getClass()) == false) {
|
||||
throw new IllegalStateException("Error merging ID token and userinfo claim value for claim [" + entry.getKey() + "]. " +
|
||||
"Cannot merge [" + value1.getClass().getName() + "] with [" + value2.getClass().getName() + "]");
|
||||
// A special handling for certain OPs that mix the usage of true and "true"
|
||||
if (value1 instanceof Boolean && value2 instanceof String && String.valueOf(value1).equals(value2)) {
|
||||
idToken.put(entry.getKey(), value1);
|
||||
} else if (value2 instanceof Boolean && value1 instanceof String && String.valueOf(value2).equals(value1)) {
|
||||
idToken.put(entry.getKey(), value2);
|
||||
} else {
|
||||
throw new IllegalStateException("Error merging ID token and userinfo claim value for claim [" + entry.getKey() + "]. " +
|
||||
"Cannot merge [" + value1.getClass().getName() + "] with [" + value2.getClass().getName() + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Map.Entry<String, Object> entry : userInfo.entrySet()) {
|
||||
|
|
|
@ -829,6 +829,51 @@ public class OpenIdConnectAuthenticatorTests extends OpenIdConnectTestCase {
|
|||
assertTrue(combinedAddress.containsKey("country"));
|
||||
}
|
||||
|
||||
public void testJsonObjectMergingWithBooleanLeniency() {
|
||||
final JSONObject idTokenObject = new JWTClaimsSet.Builder()
|
||||
.claim("email_verified", true)
|
||||
.claim("email_verified_1", "true")
|
||||
.claim("email_verified_2", false)
|
||||
.claim("email_verified_3", "false")
|
||||
.build()
|
||||
.toJSONObject();
|
||||
final JSONObject userInfoObject = new JWTClaimsSet.Builder()
|
||||
.claim("email_verified", "true")
|
||||
.claim("email_verified_1", true)
|
||||
.claim("email_verified_2", "false")
|
||||
.claim("email_verified_3", false)
|
||||
.build()
|
||||
.toJSONObject();
|
||||
OpenIdConnectAuthenticator.mergeObjects(idTokenObject, userInfoObject);
|
||||
assertSame(Boolean.TRUE, idTokenObject.get("email_verified"));
|
||||
assertSame(Boolean.TRUE, idTokenObject.get("email_verified_1"));
|
||||
assertSame(Boolean.FALSE, idTokenObject.get("email_verified_2"));
|
||||
assertSame(Boolean.FALSE, idTokenObject.get("email_verified_3"));
|
||||
|
||||
final JSONObject idTokenObject1 = new JWTClaimsSet.Builder()
|
||||
.claim("email_verified", true)
|
||||
.build()
|
||||
.toJSONObject();
|
||||
final JSONObject userInfoObject1 = new JWTClaimsSet.Builder()
|
||||
.claim("email_verified", "false")
|
||||
.build()
|
||||
.toJSONObject();
|
||||
IllegalStateException e =
|
||||
expectThrows(IllegalStateException.class, () -> OpenIdConnectAuthenticator.mergeObjects(idTokenObject1, userInfoObject1));
|
||||
assertThat(e.getMessage(), containsString("Cannot merge [java.lang.Boolean] with [java.lang.String]"));
|
||||
|
||||
final JSONObject idTokenObject2 = new JWTClaimsSet.Builder()
|
||||
.claim("email_verified", true)
|
||||
.build()
|
||||
.toJSONObject();
|
||||
final JSONObject userInfoObject2 = new JWTClaimsSet.Builder()
|
||||
.claim("email_verified", "yes")
|
||||
.build()
|
||||
.toJSONObject();
|
||||
e = expectThrows(IllegalStateException.class, () -> OpenIdConnectAuthenticator.mergeObjects(idTokenObject2, userInfoObject2));
|
||||
assertThat(e.getMessage(), containsString("Cannot merge [java.lang.Boolean] with [java.lang.String]"));
|
||||
}
|
||||
|
||||
private OpenIdConnectProviderConfiguration getOpConfig() throws URISyntaxException {
|
||||
return new OpenIdConnectProviderConfiguration(
|
||||
new Issuer("https://op.example.com"),
|
||||
|
|
Loading…
Reference in New Issue