diff --git a/examples/ldap/ldaprealm.json b/examples/ldap/ldaprealm.json
index 8a04b3e63e..16309245dd 100644
--- a/examples/ldap/ldaprealm.json
+++ b/examples/ldap/ldaprealm.json
@@ -129,7 +129,7 @@
"config" : {
"Claim JSON Type" : "String",
"user.attribute" : "picture",
- "claim.name" : "profile_picture",
+ "claim.name" : "picture",
"multivalued": "false",
"id.token.claim" : "true",
"access.token.claim" : "true"
diff --git a/examples/ldap/src/main/java/org/keycloak/example/ldap/LDAPPictureServlet.java b/examples/ldap/src/main/java/org/keycloak/example/ldap/LDAPPictureServlet.java
index 3ca7856254..fe5a983643 100644
--- a/examples/ldap/src/main/java/org/keycloak/example/ldap/LDAPPictureServlet.java
+++ b/examples/ldap/src/main/java/org/keycloak/example/ldap/LDAPPictureServlet.java
@@ -45,23 +45,14 @@ public class LDAPPictureServlet extends HttpServlet {
KeycloakSecurityContext securityContext = (KeycloakSecurityContext) req.getAttribute(KeycloakSecurityContext.class.getName());
IDToken idToken = securityContext.getIdToken();
- // TODO: Use idToken.getPicture() instead
- Object profilePicture = idToken.getOtherClaims().get("profile_picture");
+ String profilePicture = idToken.getPicture();
if (profilePicture != null) {
- String base64EncodedPicture = getBase64EncodedPicture(profilePicture);
- byte[] decodedPicture = Base64.decode(base64EncodedPicture);
+ byte[] decodedPicture = Base64.decode(profilePicture);
outputStream.write(decodedPicture);
}
outputStream.flush();
}
- private String getBase64EncodedPicture(Object profilePicture) {
- if (profilePicture instanceof List) {
- return ((List) profilePicture).get(0).toString();
- } else {
- return profilePicture.toString();
- }
- }
}
diff --git a/examples/ldap/src/main/webapp/index.jsp b/examples/ldap/src/main/webapp/index.jsp
index 11560493b7..683e5b1652 100644
--- a/examples/ldap/src/main/webapp/index.jsp
+++ b/examples/ldap/src/main/webapp/index.jsp
@@ -37,21 +37,18 @@
Full Name: <%=idToken.getName()%>
First: <%=idToken.getGivenName()%>
Last: <%=idToken.getFamilyName()%>
+ <% if (idToken.getPicture() != null) { %>
+ Profile picture:
+ <% } %>
ID Token - other claims
<%
for (Map.Entry claim : idToken.getOtherClaims().entrySet()) {
- if (!claim.getKey().equals("profile_picture")) {
%>
<%= claim.getKey() %>: <%= claim.getValue().toString() %>
<%
- } else {
-%>
-
Profile picture:
-<%
- }
}
%>
diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java
index 949c3a28a0..afdf6684eb 100755
--- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java
+++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProvider.java
@@ -201,6 +201,7 @@ public class LDAPStorageProvider implements UserStorageProvider,
LDAPObject ldapUser = LDAPUtils.addUserToLDAP(this, realm, user);
LDAPUtils.checkUuid(ldapUser, ldapIdentityStore.getConfig());
user.setSingleAttribute(LDAPConstants.LDAP_ID, ldapUser.getUuid());
+ user.setSingleAttribute(LDAPConstants.LDAP_ENTRY_DN, ldapUser.getDn().toString());
return proxy(realm, user, ldapUser);
}
@@ -421,6 +422,7 @@ public class LDAPStorageProvider implements UserStorageProvider,
String userDN = ldapUser.getDn().toString();
imported.setFederationLink(model.getId());
imported.setSingleAttribute(LDAPConstants.LDAP_ID, ldapUser.getUuid());
+ imported.setSingleAttribute(LDAPConstants.LDAP_ENTRY_DN, userDN);
logger.debugf("Imported new user from LDAP to Keycloak DB. Username: [%s], Email: [%s], LDAP_ID: [%s], LDAP Entry DN: [%s]", imported.getUsername(), imported.getEmail(),
ldapUser.getUuid(), userDN);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPMultipleAttributesTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPMultipleAttributesTest.java
index 7de1ae9962..dce0f60d64 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPMultipleAttributesTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/ldap/LDAPMultipleAttributesTest.java
@@ -56,6 +56,7 @@ import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
/**
* @author Marek Posolda
@@ -66,7 +67,15 @@ public class LDAPMultipleAttributesTest {
protected String APP_SERVER_BASE_URL = "http://localhost:8081";
protected String LOGIN_URL = OIDCLoginProtocolService.authUrl(UriBuilder.fromUri(APP_SERVER_BASE_URL + "/auth")).build("test").toString();
- private static LDAPRule ldapRule = new LDAPRule();
+
+ // Skip this test on MSAD due to lack of supported user multivalued attributes
+ private static LDAPRule ldapRule = new LDAPRule((Map ldapConfig) -> {
+
+ String vendor = ldapConfig.get(LDAPConstants.VENDOR);
+ return (vendor.equals(LDAPConstants.VENDOR_ACTIVE_DIRECTORY));
+
+ });
+
private static ComponentModel ldapModel = null;
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/KerberosRule.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/KerberosRule.java
index 8d46513ac5..38a1df20a6 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/KerberosRule.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/KerberosRule.java
@@ -36,6 +36,11 @@ public class KerberosRule extends LDAPRule {
private final String configLocation;
public KerberosRule(String configLocation) {
+ this(configLocation, null);
+ }
+
+ public KerberosRule(String configLocation, LDAPRuleCondition condition) {
+ super(condition);
this.configLocation = configLocation;
// Global kerberos configuration
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/LDAPRule.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/LDAPRule.java
index 4bf0e4c449..6dbc938ec2 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/LDAPRule.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/LDAPRule.java
@@ -17,7 +17,10 @@
package org.keycloak.testsuite.rule;
-import org.junit.rules.ExternalResource;
+import org.jboss.logging.Logger;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
import org.keycloak.testsuite.federation.ldap.LDAPTestConfiguration;
import org.keycloak.util.ldap.LDAPEmbeddedServer;
@@ -25,28 +28,76 @@ import java.util.Map;
import java.util.Properties;
/**
+ * This rule handles:
+ * - Reading of LDAP configuration from properties file
+ * - Eventually start+stop of LDAP embedded server.
+ * - Eventually allows to ignore the test if particular condition is not met. This allows to run specific tests just for some LDAP vendors
+ *
* @author Marek Posolda
*/
-public class LDAPRule extends ExternalResource {
+public class LDAPRule implements TestRule {
+
+ private static final Logger logger = Logger.getLogger(LDAPRule.class);
public static final String LDAP_CONNECTION_PROPERTIES_LOCATION = "ldap/ldap-connection.properties";
protected LDAPTestConfiguration ldapTestConfiguration;
protected LDAPEmbeddedServer ldapEmbeddedServer;
+ private final LDAPRuleCondition condition;
+
+
+ public LDAPRule() {
+ this(null);
+ }
+
+ public LDAPRule(LDAPRuleCondition condition) {
+ this.condition = condition;
+ }
+
+
@Override
- protected void before() throws Throwable {
+ public Statement apply(Statement base, Description description) {
+ return new Statement() {
+
+ @Override
+ public void evaluate() throws Throwable {
+ boolean skipTest = before();
+
+ if (skipTest) {
+ logger.infof("Skip %s due to LDAPRuleCondition not met", description.getDisplayName());
+ return;
+ }
+
+ try {
+ base.evaluate();
+ } finally {
+ after();
+ }
+ }
+ };
+ }
+
+
+ // Return true if test should be skipped
+ protected boolean before() throws Throwable {
String connectionPropsLocation = getConnectionPropertiesLocation();
ldapTestConfiguration = LDAPTestConfiguration.readConfiguration(connectionPropsLocation);
+ if (condition != null && condition.skipTest(ldapTestConfiguration.getLDAPConfig())) {
+ return true;
+ }
+
if (ldapTestConfiguration.isStartEmbeddedLdapLerver()) {
ldapEmbeddedServer = createServer();
ldapEmbeddedServer.init();
ldapEmbeddedServer.start();
}
+
+ return false;
}
- @Override
+
protected void after() {
try {
if (ldapEmbeddedServer != null) {
@@ -78,4 +129,12 @@ public class LDAPRule extends ExternalResource {
public int getSleepTime() {
return ldapTestConfiguration.getSleepTime();
}
+
+
+ // Allows to skip particular LDAP test just under specific conditions (eg. some test running just on Active Directory)
+ public interface LDAPRuleCondition {
+
+ boolean skipTest(Map ldapConfig);
+
+ }
}
diff --git a/testsuite/integration/src/test/resources/log4j.properties b/testsuite/integration/src/test/resources/log4j.properties
index 22a890dafb..4cc1f91c42 100755
--- a/testsuite/integration/src/test/resources/log4j.properties
+++ b/testsuite/integration/src/test/resources/log4j.properties
@@ -60,6 +60,9 @@ log4j.logger.org.keycloak.connections.jpa.HibernateStatsReporter=debug
# Enable to view ldap logging
# log4j.logger.org.keycloak.storage.ldap=trace
+# Enable to view queries to LDAP
+# log4j.logger.org.keycloak.storage.ldap.idm.store.ldap.LDAPIdentityStore=trace
+
# Enable to view kerberos/spnego logging
# log4j.logger.org.keycloak.federation.kerberos=trace