use of org.keycloak.storage.ldap.mappers.LDAPStorageMapper in project keycloak by keycloak.
the class LDAPStorageProvider method importUserFromLDAP.
protected UserModel importUserFromLDAP(KeycloakSession session, RealmModel realm, LDAPObject ldapUser) {
String ldapUsername = LDAPUtils.getUsername(ldapUser, ldapIdentityStore.getConfig());
LDAPUtils.checkUuid(ldapUser, ldapIdentityStore.getConfig());
UserModel imported = null;
if (model.isImportEnabled()) {
// Search if there is already an existing user, which means the username might have changed in LDAP without Keycloak knowing about it
UserModel existingLocalUser = session.userLocalStorage().searchForUserByUserAttributeStream(realm, LDAPConstants.LDAP_ID, ldapUser.getUuid()).findFirst().orElse(null);
if (existingLocalUser != null) {
imported = existingLocalUser;
// Need to evict the existing user from cache
if (session.userCache() != null) {
session.userCache().evict(realm, existingLocalUser);
}
} else {
imported = session.userLocalStorage().addUser(realm, ldapUsername);
}
} else {
InMemoryUserAdapter adapter = new InMemoryUserAdapter(session, realm, new StorageId(model.getId(), ldapUsername).getId());
adapter.addDefaults();
imported = adapter;
}
imported.setEnabled(true);
UserModel finalImported = imported;
realm.getComponentsStream(model.getId(), LDAPStorageMapper.class.getName()).sorted(ldapMappersComparator.sortDesc()).forEachOrdered(mapperModel -> {
if (logger.isTraceEnabled()) {
logger.tracef("Using mapper %s during import user from LDAP", mapperModel);
}
LDAPStorageMapper ldapMapper = mapperManager.getMapper(mapperModel);
ldapMapper.onImportUserFromLDAP(ldapUser, finalImported, realm, true);
});
String userDN = ldapUser.getDn().toString();
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, false);
return proxy;
}
use of org.keycloak.storage.ldap.mappers.LDAPStorageMapper in project keycloak by keycloak.
the class LDAPStorageProvider method proxy.
protected UserModel proxy(RealmModel realm, UserModel local, LDAPObject ldapObject, boolean newUser) {
UserModel existing = userManager.getManagedProxiedUser(local.getId());
if (existing != null) {
return existing;
}
// We need to avoid having CachedUserModel as cache is upper-layer then LDAP. Hence having CachedUserModel here may cause StackOverflowError
if (local instanceof CachedUserModel) {
local = session.userStorageManager().getUserById(realm, local.getId());
existing = userManager.getManagedProxiedUser(local.getId());
if (existing != null) {
return existing;
}
}
UserModel proxied = local;
checkDNChanged(realm, local, ldapObject);
switch(editMode) {
case READ_ONLY:
if (model.isImportEnabled()) {
proxied = new ReadonlyLDAPUserModelDelegate(local);
} else {
proxied = new ReadOnlyUserModelDelegate(local);
}
break;
case WRITABLE:
case UNSYNCED:
// This check is skipped when register new user as there are many "generic" attributes always written (EG. enabled, emailVerified) and those are usually unsupported by LDAP schema
if (!model.isImportEnabled() && !newUser) {
UserModel readOnlyDelegate = new ReadOnlyUserModelDelegate(local, ModelException::new);
proxied = new LDAPWritesOnlyUserModelDelegate(readOnlyDelegate, this);
}
break;
}
AtomicReference<UserModel> proxy = new AtomicReference<>(proxied);
realm.getComponentsStream(model.getId(), LDAPStorageMapper.class.getName()).sorted(ldapMappersComparator.sortAsc()).forEachOrdered(mapperModel -> {
LDAPStorageMapper ldapMapper = mapperManager.getMapper(mapperModel);
proxy.set(ldapMapper.proxy(ldapObject, proxy.get(), realm));
});
proxied = proxy.get();
if (!model.isImportEnabled()) {
proxied = new UpdateOnlyChangeUserModelDelegate(proxied);
}
userManager.setManagedProxiedUser(proxied, ldapObject);
return proxied;
}
use of org.keycloak.storage.ldap.mappers.LDAPStorageMapper in project keycloak by keycloak.
the class LDAPQuery method getResultList.
public List<LDAPObject> getResultList() {
// Apply mappers now
LDAPMappersComparator ldapMappersComparator = new LDAPMappersComparator(ldapFedProvider.getLdapIdentityStore().getConfig());
Collections.sort(mappers, ldapMappersComparator.sortAsc());
for (ComponentModel mapperModel : mappers) {
LDAPStorageMapper fedMapper = ldapFedProvider.getMapperManager().getMapper(mapperModel);
fedMapper.beforeLDAPQuery(this);
}
List<LDAPObject> result = new ArrayList<LDAPObject>();
try {
for (LDAPObject ldapObject : ldapFedProvider.getLdapIdentityStore().fetchQueryResults(this)) {
result.add(ldapObject);
}
} catch (Exception e) {
throw new ModelException("LDAP Query failed", e);
}
return result;
}
use of org.keycloak.storage.ldap.mappers.LDAPStorageMapper in project keycloak by keycloak.
the class LDAPUtils method addUserToLDAP.
/**
* @param ldapProvider
* @param realm
* @param user
* @return newly created LDAPObject with all the attributes, uuid and DN properly set
*/
public static LDAPObject addUserToLDAP(LDAPStorageProvider ldapProvider, RealmModel realm, UserModel user) {
LDAPObject ldapUser = new LDAPObject();
LDAPIdentityStore ldapStore = ldapProvider.getLdapIdentityStore();
LDAPConfig ldapConfig = ldapStore.getConfig();
ldapUser.setRdnAttributeName(ldapConfig.getRdnLdapAttribute());
ldapUser.setObjectClasses(ldapConfig.getUserObjectClasses());
LDAPMappersComparator ldapMappersComparator = new LDAPMappersComparator(ldapConfig);
realm.getComponentsStream(ldapProvider.getModel().getId(), LDAPStorageMapper.class.getName()).sorted(ldapMappersComparator.sortAsc()).forEachOrdered(mapperModel -> {
LDAPStorageMapper ldapMapper = ldapProvider.getMapperManager().getMapper(mapperModel);
ldapMapper.onRegisterUserToLDAP(ldapUser, user, realm);
});
LDAPUtils.computeAndSetDn(ldapConfig, ldapUser);
ldapStore.add(ldapUser);
return ldapUser;
}
use of org.keycloak.storage.ldap.mappers.LDAPStorageMapper in project keycloak by keycloak.
the class LDAPStorageProviderFactory method importLdapUsers.
protected SynchronizationResult importLdapUsers(KeycloakSessionFactory sessionFactory, final String realmId, final ComponentModel fedModel, List<LDAPObject> ldapUsers) {
final SynchronizationResult syncResult = new SynchronizationResult();
class BooleanHolder {
private boolean value = true;
}
final BooleanHolder exists = new BooleanHolder();
for (final LDAPObject ldapUser : ldapUsers) {
try {
// Process each user in it's own transaction to avoid global fail
KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
@Override
public void run(KeycloakSession session) {
LDAPStorageProvider ldapFedProvider = (LDAPStorageProvider) session.getProvider(UserStorageProvider.class, fedModel);
RealmModel currentRealm = session.realms().getRealm(realmId);
session.getContext().setRealm(currentRealm);
String username = LDAPUtils.getUsername(ldapUser, ldapFedProvider.getLdapIdentityStore().getConfig());
exists.value = true;
LDAPUtils.checkUuid(ldapUser, ldapFedProvider.getLdapIdentityStore().getConfig());
UserModel currentUserLocal = session.userLocalStorage().getUserByUsername(currentRealm, username);
Optional<UserModel> userModelOptional = session.userLocalStorage().searchForUserByUserAttributeStream(currentRealm, LDAPConstants.LDAP_ID, ldapUser.getUuid()).findFirst();
if (!userModelOptional.isPresent() && currentUserLocal == null) {
// Add new user to Keycloak
exists.value = false;
ldapFedProvider.importUserFromLDAP(session, currentRealm, ldapUser);
syncResult.increaseAdded();
} else {
UserModel currentUser = userModelOptional.isPresent() ? userModelOptional.get() : currentUserLocal;
if ((fedModel.getId().equals(currentUser.getFederationLink())) && (ldapUser.getUuid().equals(currentUser.getFirstAttribute(LDAPConstants.LDAP_ID)))) {
// Update keycloak user
LDAPMappersComparator ldapMappersComparator = new LDAPMappersComparator(ldapFedProvider.getLdapIdentityStore().getConfig());
currentRealm.getComponentsStream(fedModel.getId(), LDAPStorageMapper.class.getName()).sorted(ldapMappersComparator.sortDesc()).forEachOrdered(mapperModel -> {
LDAPStorageMapper ldapMapper = ldapFedProvider.getMapperManager().getMapper(mapperModel);
ldapMapper.onImportUserFromLDAP(ldapUser, currentUser, currentRealm, false);
});
UserCache userCache = session.userCache();
if (userCache != null) {
userCache.evict(currentRealm, currentUser);
}
logger.debugf("Updated user from LDAP: %s", currentUser.getUsername());
syncResult.increaseUpdated();
} else {
logger.warnf("User with ID '%s' is not updated during sync as he already exists in Keycloak database but is not linked to federation provider '%s'", ldapUser.getUuid(), fedModel.getName());
syncResult.increaseFailed();
}
}
}
});
} catch (ModelException me) {
logger.error("Failed during import user from LDAP", me);
syncResult.increaseFailed();
// Remove user if we already added him during this transaction
if (!exists.value) {
KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
@Override
public void run(KeycloakSession session) {
LDAPStorageProvider ldapFedProvider = (LDAPStorageProvider) session.getProvider(UserStorageProvider.class, fedModel);
RealmModel currentRealm = session.realms().getRealm(realmId);
session.getContext().setRealm(currentRealm);
String username = null;
try {
username = LDAPUtils.getUsername(ldapUser, ldapFedProvider.getLdapIdentityStore().getConfig());
} catch (ModelException ignore) {
}
if (username != null) {
UserModel existing = session.userLocalStorage().getUserByUsername(currentRealm, username);
if (existing != null) {
UserCache userCache = session.userCache();
if (userCache != null) {
userCache.evict(currentRealm, existing);
}
session.userLocalStorage().removeUser(currentRealm, existing);
}
}
}
});
}
}
}
return syncResult;
}
Aggregations