[KEYCLOAK-4778] Fix for Oracle null value when having an empty String as attribute value (#4406)

* Add client.name as a second parameter to the title expressions in login template

* Fixing tooltip.

* pt_BR localization for admin screens.

* Reverting login.ftl

* Added all tooltip messages - even the ones not translated.
Translated around 150 messages todas.

* More translations.

* Fixing wrong edit.

* [KEYCLOAK-4778] Null check on Attribute value. This value can be null when retrieved from an Oracle database.

* [KEYCLOAK-4778] Create unit tests for empty and null values.

* [KEYCLOAK-4778] Move empty and null attributes tests to a separated test method; change tests to empty or null Strings.

* [KEYCLOAK-4778] Check if value is null and set it as empty array. In the former code if null was received it would generate an array with 1 string element ["null"]. Also if we set value as null instead of ArrayList, later when the rest call is executed it will generate the same incorrect array again.

* [KEYCLOAK-4778] Tests clean up.
This commit is contained in:
filipelautert 2017-08-31 01:09:41 -03:00 committed by Stian Thorgersen
parent 924b4f651a
commit e055589448
3 changed files with 60 additions and 3 deletions

View file

@ -23,6 +23,7 @@ import org.keycloak.json.StringListMapDeserializer;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.ArrayList;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -157,7 +158,7 @@ public class UserRepresentation {
public UserRepresentation singleAttribute(String name, String value) { public UserRepresentation singleAttribute(String name, String value) {
if (this.attributes == null) attributes = new HashMap<>(); if (this.attributes == null) attributes = new HashMap<>();
attributes.put(name, Arrays.asList(value)); attributes.put(name, (value == null ? new ArrayList<String>() : Arrays.asList(value)));
return this; return this;
} }

View file

@ -86,7 +86,7 @@ public class OIDCAttributeMapperHelper {
} }
private static Object convertToType(String type, Object attributeValue) { private static Object convertToType(String type, Object attributeValue) {
if (type == null) return attributeValue; if (type == null || attributeValue == null) return attributeValue;
switch (type) { switch (type) {
case "boolean": case "boolean":
Boolean booleanObject = getBoolean(attributeValue); Boolean booleanObject = getBoolean(attributeValue);

View file

@ -52,6 +52,7 @@ import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isEmptyString;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
@ -123,7 +124,6 @@ public class OIDCProtocolMappersTest extends AbstractKeycloakTest {
user.singleAttribute("formatted", "6 Foo Street"); user.singleAttribute("formatted", "6 Foo Street");
user.singleAttribute("phone", "617-777-6666"); user.singleAttribute("phone", "617-777-6666");
List<String> departments = Arrays.asList("finance", "development"); List<String> departments = Arrays.asList("finance", "development");
user.getAttributes().put("departments", departments); user.getAttributes().put("departments", departments);
userResource.update(user); userResource.update(user);
@ -242,6 +242,62 @@ public class OIDCProtocolMappersTest extends AbstractKeycloakTest {
events.clear(); events.clear();
} }
@Test
public void testNullOrEmptyTokenMapping() throws Exception {
{
UserResource userResource = findUserByUsernameId(adminClient.realm("test"), "test-user@localhost");
UserRepresentation user = userResource.toRepresentation();
user.singleAttribute("empty", "");
user.singleAttribute("null", null);
userResource.update(user);
ClientResource app = findClientResourceByClientId(adminClient.realm("test"), "test-app");
app.getProtocolMappers().createMapper(createClaimMapper("empty", "empty", "empty", "String", true, "", true, true, false)).close();
app.getProtocolMappers().createMapper(createClaimMapper("null", "null", "null", "String", true, "", true, true, false)).close();
}
{
OAuthClient.AccessTokenResponse response = browserLogin("password", "test-user@localhost", "password");
IDToken idToken = oauth.verifyIDToken(response.getIdToken());
Object empty = idToken.getOtherClaims().get("empty");
assertThat((empty == null ? null : (String) empty), isEmptyString());
Object nulll = idToken.getOtherClaims().get("null");
assertNull(nulll);
AccessToken accessToken = oauth.verifyToken(response.getAccessToken());
oauth.openLogout();
}
// undo mappers
{
ClientResource app = findClientByClientId(adminClient.realm("test"), "test-app");
ClientRepresentation clientRepresentation = app.toRepresentation();
for (ProtocolMapperRepresentation model : clientRepresentation.getProtocolMappers()) {
if (model.getName().equals("empty")
|| model.getName().equals("null")
) {
app.getProtocolMappers().delete(model.getId());
}
}
}
events.clear();
{
OAuthClient.AccessTokenResponse response = browserLogin("password", "test-user@localhost", "password");
IDToken idToken = oauth.verifyIDToken(response.getIdToken());
assertNull(idToken.getAddress());
assertNull(idToken.getOtherClaims().get("empty"));
assertNull(idToken.getOtherClaims().get("null"));
oauth.openLogout();
}
events.clear();
}
@Test @Test
public void testUserRoleToAttributeMappers() throws Exception { public void testUserRoleToAttributeMappers() throws Exception {