KEYCLOAK-8316 Add an option to ldap provider to trust emails on import

Signed-off-by: Cédric Couralet <cedric.couralet@insee.fr>
This commit is contained in:
Cédric Couralet 2019-10-04 16:28:02 +02:00 committed by Marek Posolda
parent 3d175dbe0c
commit 5f006b283a
7 changed files with 60 additions and 2 deletions

View file

@ -22,6 +22,7 @@ import org.keycloak.models.LDAPConstants;
import org.keycloak.storage.UserStorageProvider;
import javax.naming.directory.SearchControls;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
@ -110,6 +111,11 @@ public class LDAPConfig {
return Boolean.parseBoolean(validatePPolicy);
}
public boolean isTrustEmail(){
String trustEmail = config.getFirst(LDAPConstants.TRUST_EMAIL);
return Boolean.parseBoolean(trustEmail);
}
public String getConnectionPooling() {
if(isStartTls()) {
return null;

View file

@ -524,8 +524,9 @@ public class LDAPStorageProvider implements UserStorageProvider,
if (model.isImportEnabled()) imported.setFederationLink(model.getId());
imported.setSingleAttribute(LDAPConstants.LDAP_ID, ldapUser.getUuid());
imported.setSingleAttribute(LDAPConstants.LDAP_ENTRY_DN, userDN);
if(getLdapIdentityStore().getConfig().isTrustEmail()){
imported.setEmailVerified(true);
}
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);
UserModel proxy = proxy(realm, imported, ldapUser);

View file

@ -149,6 +149,10 @@ public class LDAPStorageProviderFactory implements UserStorageProviderFactory<LD
.type(ProviderConfigProperty.BOOLEAN_TYPE)
.defaultValue("false")
.add()
.property().name(LDAPConstants.TRUST_EMAIL)
.type(ProviderConfigProperty.BOOLEAN_TYPE)
.defaultValue("false")
.add()
.property().name(LDAPConstants.USE_TRUSTSTORE_SPI)
.type(ProviderConfigProperty.STRING_TYPE)
.defaultValue("ldapsOnly")

View file

@ -72,6 +72,8 @@ public class LDAPConstants {
public static final String VALIDATE_PASSWORD_POLICY = "validatePasswordPolicy";
public static final String TRUST_EMAIL = "trustEmail";
// Count of users processed per single transaction during sync process
public static final String BATCH_SIZE_FOR_SYNC = "batchSizeForSync";
public static final int DEFAULT_BATCH_SIZE_FOR_SYNC = 1000;

View file

@ -1114,4 +1114,41 @@ public class LDAPProvidersIntegrationTest extends AbstractLDAPTest {
setTimeOffset(0);
}
@Test
public void testEmailVerifiedFromImport(){
// Test trusted email option
testingClient.server().run(session -> {
LDAPTestContext ctx = LDAPTestContext.init(session);
ctx.getLdapModel().put(LDAPConstants.TRUST_EMAIL, "true");
ctx.getRealm().updateComponent(ctx.getLdapModel());
LDAPTestUtils.addLDAPUser(ctx.getLdapProvider(), ctx.getRealm(), "testUserVerified", "John", "Email", "john@test.com", null, "1234");
});
loginPage.open();
loginPage.login("testuserVerified", "password");
testingClient.server().run(session -> {
RealmModel appRealm = session.realms().getRealmByName(TEST_REALM_NAME);
List<UserModel> userVerified = session.users().searchForUser("john@test.com", appRealm);
Assert.assertTrue(userVerified.get(0).isEmailVerified());
});
//Test untrusted email option
testingClient.server().run(session -> {
LDAPTestContext ctx = LDAPTestContext.init(session);
ctx.getLdapModel().put(LDAPConstants.TRUST_EMAIL, "false");
ctx.getRealm().updateComponent(ctx.getLdapModel());
LDAPTestUtils.addLDAPUser(ctx.getLdapProvider(), ctx.getRealm(), "testUserNotVerified", "John", "Email", "john2@test.com", null, "1234");
});
loginPage.open();
loginPage.login("testuserNotVerified", "password");
testingClient.server().run(session -> {
RealmModel appRealm = session.realms().getRealmByName(TEST_REALM_NAME);
List<UserModel> userNotVerified = session.users().searchForUser("john2@test.com", appRealm);
Assert.assertFalse(userNotVerified.get(0).isEmailVerified());
});
}
}

View file

@ -953,6 +953,7 @@ ldap.search-scope.tooltip=For one level, we search for users just in DNs specifi
use-truststore-spi=Use Truststore SPI
ldap.use-truststore-spi.tooltip=Specifies whether LDAP connection will use the truststore SPI with the truststore configured in standalone.xml/domain.xml. 'Always' means that it will always use it. 'Never' means that it won't use it. 'Only for ldaps' means that it will use if your connection URL use ldaps. Note even if standalone.xml/domain.xml is not configured, the default Java cacerts or certificate specified by 'javax.net.ssl.trustStore' property will be used.
validate-password-policy=Validate Password Policy
trust-email=Trust Email
connection-pooling=Connection Pooling
connection-pooling-settings=Connection Pooling Settings
connection-pooling-authentication=Connection Pooling Authentication

View file

@ -191,6 +191,13 @@
</div>
<kc-tooltip>{{:: 'ldap.validate-password-policy.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix">
<label class="col-md-2 control-label" for="trustEmail">{{:: 'trust-email' | translate}}</label>
<div class="col-md-6">
<input ng-model="instance.config['trustEmail'][0]" name="trustEmail" id="trustEmail" onoffswitchvalue on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
</div>
<kc-tooltip>{{:: 'trust-email.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="useTruststoreSpi">{{:: 'use-truststore-spi' | translate}}</label>
<div class="col-md-6">