Search in sources :

Example 6 with UserCache

use of org.keycloak.models.cache.UserCache 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;
}
Also used : SPNEGOAuthenticator(org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator) FullNameLDAPStorageMapperFactory(org.keycloak.storage.ldap.mappers.FullNameLDAPStorageMapperFactory) Date(java.util.Date) LDAPStorageMapper(org.keycloak.storage.ldap.mappers.LDAPStorageMapper) Config(org.keycloak.Config) FullNameLDAPStorageMapper(org.keycloak.storage.ldap.mappers.FullNameLDAPStorageMapper) ProviderConfigurationBuilder(org.keycloak.provider.ProviderConfigurationBuilder) LDAPConstants(org.keycloak.models.LDAPConstants) Map(java.util.Map) ComponentModel(org.keycloak.component.ComponentModel) CredentialRepresentation(org.keycloak.representations.idm.CredentialRepresentation) UserStorageProviderModel(org.keycloak.storage.UserStorageProviderModel) UserAttributeLDAPStorageMapperFactory(org.keycloak.storage.ldap.mappers.UserAttributeLDAPStorageMapperFactory) UserStorageProviderFactory(org.keycloak.storage.UserStorageProviderFactory) HardcodedLDAPAttributeMapper(org.keycloak.storage.ldap.mappers.HardcodedLDAPAttributeMapper) HardcodedLDAPAttributeMapperFactory(org.keycloak.storage.ldap.mappers.HardcodedLDAPAttributeMapperFactory) RealmModel(org.keycloak.models.RealmModel) LDAPConfigDecorator(org.keycloak.storage.ldap.mappers.LDAPConfigDecorator) CredentialHelper(org.keycloak.utils.CredentialHelper) CommonKerberosConfig(org.keycloak.federation.kerberos.CommonKerberosConfig) Collectors(java.util.stream.Collectors) LDAPObject(org.keycloak.storage.ldap.idm.model.LDAPObject) ImportSynchronization(org.keycloak.storage.user.ImportSynchronization) List(java.util.List) UserAttributeLDAPStorageMapper(org.keycloak.storage.ldap.mappers.UserAttributeLDAPStorageMapper) KerberosUsernamePasswordAuthenticator(org.keycloak.federation.kerberos.impl.KerberosUsernamePasswordAuthenticator) KeycloakSessionFactory(org.keycloak.models.KeycloakSessionFactory) Optional(java.util.Optional) Condition(org.keycloak.storage.ldap.idm.query.Condition) ComponentValidationException(org.keycloak.component.ComponentValidationException) KeycloakModelUtils(org.keycloak.models.utils.KeycloakModelUtils) Logger(org.jboss.logging.Logger) ProviderConfigProperty(org.keycloak.provider.ProviderConfigProperty) Function(java.util.function.Function) LDAPIdentityStore(org.keycloak.storage.ldap.idm.store.ldap.LDAPIdentityStore) UserModel(org.keycloak.models.UserModel) AuthenticationExecutionModel(org.keycloak.models.AuthenticationExecutionModel) KeycloakSessionTask(org.keycloak.models.KeycloakSessionTask) LDAPQueryConditionsBuilder(org.keycloak.storage.ldap.idm.query.internal.LDAPQueryConditionsBuilder) KerberosConstants(org.keycloak.common.constants.KerberosConstants) UserStorageProvider(org.keycloak.storage.UserStorageProvider) LDAPMappersComparator(org.keycloak.storage.ldap.mappers.LDAPMappersComparator) KerberosServerSubjectAuthenticator(org.keycloak.federation.kerberos.impl.KerberosServerSubjectAuthenticator) KeycloakSession(org.keycloak.models.KeycloakSession) LDAPQuery(org.keycloak.storage.ldap.idm.query.internal.LDAPQuery) UserCache(org.keycloak.models.cache.UserCache) MSADUserAccountControlStorageMapperFactory(org.keycloak.storage.ldap.mappers.msad.MSADUserAccountControlStorageMapperFactory) ModelException(org.keycloak.models.ModelException) SynchronizationResult(org.keycloak.storage.user.SynchronizationResult) LDAPStorageMapper(org.keycloak.storage.ldap.mappers.LDAPStorageMapper) FullNameLDAPStorageMapper(org.keycloak.storage.ldap.mappers.FullNameLDAPStorageMapper) UserAttributeLDAPStorageMapper(org.keycloak.storage.ldap.mappers.UserAttributeLDAPStorageMapper) Optional(java.util.Optional) LDAPMappersComparator(org.keycloak.storage.ldap.mappers.LDAPMappersComparator) ModelException(org.keycloak.models.ModelException) UserCache(org.keycloak.models.cache.UserCache) RealmModel(org.keycloak.models.RealmModel) UserModel(org.keycloak.models.UserModel) UserStorageProvider(org.keycloak.storage.UserStorageProvider) KeycloakSessionTask(org.keycloak.models.KeycloakSessionTask) KeycloakSession(org.keycloak.models.KeycloakSession) LDAPObject(org.keycloak.storage.ldap.idm.model.LDAPObject) SynchronizationResult(org.keycloak.storage.user.SynchronizationResult)

Example 7 with UserCache

use of org.keycloak.models.cache.UserCache in project keycloak by keycloak.

the class LDAPStorageProvider method findOrCreateAuthenticatedUser.

/**
 * Called after successful kerberos authentication
 *
 * @param realm realm
 * @param username username without realm prefix
 * @return finded or newly created user
 */
protected UserModel findOrCreateAuthenticatedUser(RealmModel realm, String username) {
    UserModel user = session.userLocalStorage().getUserByUsername(realm, username);
    if (user != null) {
        logger.debugf("Kerberos authenticated user [%s] found in Keycloak storage", username);
        if (!model.getId().equals(user.getFederationLink())) {
            logger.warnf("User with username [%s] already exists, but is not linked to provider [%s]", username, model.getName());
            return null;
        } else {
            LDAPObject ldapObject = loadAndValidateUser(realm, user);
            if (ldapObject != null) {
                return proxy(realm, user, ldapObject, false);
            } else {
                logger.warnf("User with username [%s] aready exists and is linked to provider [%s] but is not valid. Stale LDAP_ID on local user is: %s", username, model.getName(), user.getFirstAttribute(LDAPConstants.LDAP_ID));
                logger.warn("Will re-create user");
                UserCache userCache = session.userCache();
                if (userCache != null) {
                    userCache.evict(realm, user);
                }
                new UserManager(session).removeUser(realm, user, session.userLocalStorage());
            }
        }
    }
    // Creating user to local storage
    logger.debugf("Kerberos authenticated user [%s] not in Keycloak storage. Creating him", username);
    return getUserByUsername(realm, username);
}
Also used : CachedUserModel(org.keycloak.models.cache.CachedUserModel) UserModel(org.keycloak.models.UserModel) UserManager(org.keycloak.models.UserManager) LDAPObject(org.keycloak.storage.ldap.idm.model.LDAPObject) UserCache(org.keycloak.models.cache.UserCache)

Example 8 with UserCache

use of org.keycloak.models.cache.UserCache in project keycloak by keycloak.

the class RealmAdminResource method clearUserCache.

/**
 * Clear user cache
 */
@Path("clear-user-cache")
@POST
public void clearUserCache() {
    auth.realm().requireManageRealm();
    UserCache cache = session.getProvider(UserCache.class);
    if (cache != null) {
        cache.clear();
    }
    adminEvent.operation(OperationType.ACTION).resourcePath(session.getContext().getUri()).success();
}
Also used : UserCache(org.keycloak.models.cache.UserCache) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST)

Example 9 with UserCache

use of org.keycloak.models.cache.UserCache in project keycloak by keycloak.

the class LDAPSyncTest method test05MissingLDAPUsernameSync.

// KEYCLOAK-1728
@Test
public void test05MissingLDAPUsernameSync() {
    String origUsernameAttrName = testingClient.server().fetch(session -> {
        LDAPTestContext ctx = LDAPTestContext.init(session);
        // Remove all users from model
        session.userLocalStorage().getUsersStream(ctx.getRealm(), true).peek(user -> System.out.println("trying to delete user: " + user.getUsername())).collect(Collectors.toList()).forEach(user -> {
            UserCache userCache = session.userCache();
            if (userCache != null) {
                userCache.evict(ctx.getRealm(), user);
            }
            session.userLocalStorage().removeUser(ctx.getRealm(), user);
        });
        // Add street mapper and add some user including street
        ComponentModel streetMapper = LDAPTestUtils.addUserAttributeMapper(ctx.getRealm(), ctx.getLdapModel(), "streetMapper", "street", LDAPConstants.STREET);
        LDAPObject streetUser = LDAPTestUtils.addLDAPUser(ctx.getLdapProvider(), ctx.getRealm(), "user8", "User8FN", "User8LN", "user8@email.org", "user8street", "126");
        // Change name of username attribute name to street
        String origUsernameAttrNamee = ctx.getLdapModel().get(LDAPConstants.USERNAME_LDAP_ATTRIBUTE);
        ctx.getLdapModel().getConfig().putSingle(LDAPConstants.USERNAME_LDAP_ATTRIBUTE, "street");
        // Need to change this due to ApacheDS pagination bug (For other LDAP servers, pagination works fine) TODO: Remove once ApacheDS upgraded and pagination is fixed
        ctx.getLdapModel().put(LDAPConstants.BATCH_SIZE_FOR_SYNC, "10");
        ctx.getRealm().updateComponent(ctx.getLdapModel());
        return origUsernameAttrNamee;
    }, String.class);
    // Just user8 synced. All others failed to sync
    testingClient.server().run(session -> {
        LDAPTestContext ctx = LDAPTestContext.init(session);
        KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
        SynchronizationResult syncResult = new UserStorageSyncManager().syncAllUsers(sessionFactory, "test", ctx.getLdapModel());
        Assert.assertEquals(1, syncResult.getAdded());
        Assert.assertTrue(syncResult.getFailed() > 0);
    });
    // Revert config changes
    ComponentRepresentation ldapRep = testRealm().components().component(ldapModelId).toRepresentation();
    if (origUsernameAttrName == null) {
        ldapRep.getConfig().remove(LDAPConstants.USERNAME_LDAP_ATTRIBUTE);
    } else {
        ldapRep.getConfig().putSingle(LDAPConstants.USERNAME_LDAP_ATTRIBUTE, origUsernameAttrName);
    }
    testRealm().components().component(ldapModelId).update(ldapRep);
    testingClient.server().run(session -> {
        LDAPTestContext ctx = LDAPTestContext.init(session);
        // Revert config changes
        ComponentModel streetMapper = LDAPTestUtils.getSubcomponentByName(ctx.getRealm(), ctx.getLdapModel(), "streetMapper");
        ctx.getRealm().removeComponent(streetMapper);
    });
}
Also used : ComponentRepresentation(org.keycloak.representations.idm.ComponentRepresentation) UserStorageSyncManager(org.keycloak.services.managers.UserStorageSyncManager) ComponentModel(org.keycloak.component.ComponentModel) LDAPObject(org.keycloak.storage.ldap.idm.model.LDAPObject) SynchronizationResult(org.keycloak.storage.user.SynchronizationResult) UserCache(org.keycloak.models.cache.UserCache) KeycloakSessionFactory(org.keycloak.models.KeycloakSessionFactory) Test(org.junit.Test)

Example 10 with UserCache

use of org.keycloak.models.cache.UserCache in project keycloak by keycloak.

the class PasswordCredentialProvider method isValid.

@Override
public boolean isValid(RealmModel realm, UserModel user, CredentialInput input) {
    if (!(input instanceof UserCredentialModel)) {
        logger.debug("Expected instance of UserCredentialModel for CredentialInput");
        return false;
    }
    if (input.getChallengeResponse() == null) {
        logger.debugv("Input password was null for user {0} ", user.getUsername());
        return false;
    }
    PasswordCredentialModel password = getPassword(realm, user);
    if (password == null) {
        logger.debugv("No password cached or stored for user {0} ", user.getUsername());
        return false;
    }
    PasswordHashProvider hash = session.getProvider(PasswordHashProvider.class, password.getPasswordCredentialData().getAlgorithm());
    if (hash == null) {
        logger.debugv("PasswordHashProvider {0} not found for user {1} ", password.getPasswordCredentialData().getAlgorithm(), user.getUsername());
        return false;
    }
    if (!hash.verify(input.getChallengeResponse(), password)) {
        logger.debugv("Failed password validation for user {0} ", user.getUsername());
        return false;
    }
    PasswordPolicy policy = realm.getPasswordPolicy();
    if (policy == null) {
        return true;
    }
    hash = getHashProvider(policy);
    if (hash == null) {
        return true;
    }
    if (hash.policyCheck(policy, password)) {
        return true;
    }
    PasswordCredentialModel newPassword = hash.encodedCredential(input.getChallengeResponse(), policy.getHashIterations());
    newPassword.setId(password.getId());
    newPassword.setCreatedDate(password.getCreatedDate());
    newPassword.setUserLabel(password.getUserLabel());
    getCredentialStore().updateCredential(realm, user, newPassword);
    UserCache userCache = session.userCache();
    if (userCache != null) {
        userCache.evict(realm, user);
    }
    return true;
}
Also used : PasswordCredentialModel(org.keycloak.models.credential.PasswordCredentialModel) PasswordPolicy(org.keycloak.models.PasswordPolicy) OnUserCache(org.keycloak.models.cache.OnUserCache) UserCache(org.keycloak.models.cache.UserCache) UserCredentialModel(org.keycloak.models.UserCredentialModel) PasswordHashProvider(org.keycloak.credential.hash.PasswordHashProvider)

Aggregations

UserCache (org.keycloak.models.cache.UserCache)14 OnUserCache (org.keycloak.models.cache.OnUserCache)5 UserModel (org.keycloak.models.UserModel)4 ComponentModel (org.keycloak.component.ComponentModel)3 KeycloakSessionFactory (org.keycloak.models.KeycloakSessionFactory)3 ModelException (org.keycloak.models.ModelException)3 PasswordPolicy (org.keycloak.models.PasswordPolicy)3 RealmModel (org.keycloak.models.RealmModel)3 UserCredentialModel (org.keycloak.models.UserCredentialModel)3 LDAPObject (org.keycloak.storage.ldap.idm.model.LDAPObject)3 List (java.util.List)2 Map (java.util.Map)2 Collectors (java.util.stream.Collectors)2 BadRequestException (javax.ws.rs.BadRequestException)2 Test (org.junit.Test)2 PasswordHashProvider (org.keycloak.credential.hash.PasswordHashProvider)2 LDAPConstants (org.keycloak.models.LDAPConstants)2 UserManager (org.keycloak.models.UserManager)2 CachedUserModel (org.keycloak.models.cache.CachedUserModel)2 PasswordCredentialModel (org.keycloak.models.credential.PasswordCredentialModel)2