KEYCLOAK-9091 Fix for claims with dots from userInfo (#6312)

* KEYCLOAK-9091 Unable to map claim attributes with dots (.) in them when claims are retrieved from userInfo endpoint
This commit is contained in:
Helge Olav Aarstein 2019-10-24 21:41:38 +02:00 committed by Marek Posolda
parent ff551c5545
commit d7a0597b1d
2 changed files with 71 additions and 65 deletions

View file

@ -26,6 +26,7 @@ import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
@ -165,21 +166,21 @@ public abstract class AbstractJsonUserAttributeMapper extends AbstractIdentityPr
return value;
}
public static Object getJsonValue(JsonNode baseNode, String fieldPath) {
logger.debug("Going to process JsonNode path " + fieldPath + " on data " + baseNode);
if (baseNode != null) {
int idx = fieldPath.indexOf(JSON_PATH_DELIMITER);
String currentFieldName = fieldPath;
if (idx > 0) {
currentFieldName = fieldPath.substring(0, idx).trim();
if (currentFieldName.isEmpty()) {
List<String> fields = OIDCAttributeMapperHelper.splitClaimPath(fieldPath);
if (fields.isEmpty() || fieldPath.endsWith(".")) {
logger.debug("JSON path is invalid " + fieldPath);
return null;
}
}
JsonNode currentNode = baseNode;
for (String currentFieldName : fields) {
// if array path, retrieve field name and index
String currentNodeName = currentFieldName;
int arrayIndex = -1;
if (currentFieldName.endsWith("]")) {
@ -189,16 +190,17 @@ public abstract class AbstractJsonUserAttributeMapper extends AbstractIdentityPr
return null;
}
try {
String is = currentFieldName.substring(bi+1, currentFieldName.length() - 1).trim();
String is = currentFieldName.substring(bi + 1, currentFieldName.length() - 1).trim();
arrayIndex = Integer.parseInt(is);
if( arrayIndex < 0) throw new ArrayIndexOutOfBoundsException();
} catch (Exception e) {
logger.debug("Invalid array index construct in " + currentFieldName);
return null;
}
currentNodeName = currentFieldName.substring(0,bi).trim();
currentNodeName = currentFieldName.substring(0, bi).trim();
}
JsonNode currentNode = baseNode.get(currentNodeName);
currentNode = currentNode.get(currentNodeName);
if (arrayIndex > -1 && currentNode.isArray()) {
logger.debug("Going to take array node at index " + arrayIndex);
currentNode = currentNode.get(arrayIndex);
@ -209,7 +211,6 @@ public abstract class AbstractJsonUserAttributeMapper extends AbstractIdentityPr
return null;
}
if (idx < 0) {
if (currentNode.isArray()) {
List<String> values = new ArrayList<>();
for (JsonNode childNode : currentNode) {
@ -222,20 +223,22 @@ public abstract class AbstractJsonUserAttributeMapper extends AbstractIdentityPr
if (values.isEmpty()) {
return null;
}
return arrayIndex == idx? values : null;
}
if (currentNode.isNull()) {
return values ;
} else if (currentNode.isNull()) {
logger.debug("JsonNode is null node for name " + currentFieldName);
return null;
} else if (!currentNode.isValueNode()) {
return currentNode;
}
} else if (currentNode.isValueNode()) {
String ret = currentNode.asText();
if (ret != null && !ret.trim().isEmpty())
return ret.trim();
} else {
return getJsonValue(currentNode, fieldPath.substring(idx + 1));
else
return null;
}
}
return currentNode;
}
return null;
}

View file

@ -39,10 +39,11 @@ public class AbstractJsonUserAttributeMapperTest {
private JsonNode getJsonNode() throws IOException {
if (baseNode == null)
baseNode = mapper.readTree("{ \"value1\" : \"v1 \",\"value_null\" : null,\"value_empty\" : \"\", \"value_b\" : true, \"value_i\" : 454, " + " \"value_array\":[\"a1\",\"a2\"], " +" \"nest1\": {\"value1\": \" fgh \",\"value_null\" : null,\"value_empty\" : \"\", \"nest2\":{\"value_b\" : false, \"value_i\" : 43}}, "+ " \"nesta\": { \"a\":[{\"av1\": \"vala1\"},{\"av1\": \"vala2\"}]}"+" }");
baseNode = mapper.readTree("{ \"dotted.claim\": \"claimValue\", \"nested.claim\" : { \"claim.with.dots\" : \"nested.claim.with.dots\"}, \"value1\" : \"v1 \",\"value_null\" : null,\"value_empty\" : \"\", \"value_b\" : true, \"value_i\" : 454, " + " \"value_array\":[\"a1\",\"a2\"], " +" \"nest1\": {\"value1\": \" fgh \",\"value_null\" : null,\"value_empty\" : \"\", \"nest2\":{\"value_b\" : false, \"value_i\" : 43}}, "+ " \"nesta\": { \"a\":[{\"av1\": \"vala1\"},{\"av1\": \"vala2\"}]}"+" }");
return baseNode;
}
@Test
public void getJsonValue_invalidPath() throws IOException {
Assert.assertNull(AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "."));
@ -68,6 +69,8 @@ public class AbstractJsonUserAttributeMapperTest {
Assert.assertEquals("true", AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_b"));
Assert.assertEquals("454", AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_i"));
Assert.assertEquals("claimValue", AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "dotted\\.claim"));
Assert.assertEquals("nested.claim.with.dots", AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nested\\.claim.claim\\.with\\.dots"));
}