Search in sources :

Example 1 with UserCache

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

the class BackwardsCompatibilityUserStorage method updateCredential.

@Override
public boolean updateCredential(RealmModel realm, UserModel user, CredentialInput input) {
    if (!(input instanceof UserCredentialModel))
        return false;
    if (input.getType().equals(UserCredentialModel.PASSWORD)) {
        // Compatibility with 4.8.3 - Using "legacy" type PasswordUserCredentialModel
        if (!(input instanceof PasswordUserCredentialModel)) {
            log.warn("Input is not PasswordUserCredentialModel");
            return false;
        }
        PasswordUserCredentialModel userCredentialModel = (PasswordUserCredentialModel) input;
        // Those are not supposed to be set when calling this method in Keycloak 4.8.3 for password credential
        assertNull(userCredentialModel.getDevice());
        assertNull(userCredentialModel.getAlgorithm());
        PasswordPolicy policy = session.getContext().getRealm().getPasswordPolicy();
        PasswordHashProvider hashProvider = getHashProvider(policy);
        CredentialModel newPassword = new CredentialModel();
        newPassword.setType(CredentialModel.PASSWORD);
        long createdDate = Time.currentTimeMillis();
        newPassword.setCreatedDate(createdDate);
        // Compatibility with 4.8.3 - Using "legacy" signature of the method on hashProvider
        hashProvider.encode(userCredentialModel.getValue(), policy.getHashIterations(), newPassword);
        // Test expected values of credentialModel
        assertEquals(newPassword.getAlgorithm(), policy.getHashAlgorithm());
        assertNotNull(newPassword.getValue());
        assertNotNull(newPassword.getSalt());
        users.get(translateUserName(user.getUsername())).hashedPassword = newPassword;
        UserCache userCache = session.userCache();
        if (userCache != null) {
            userCache.evict(realm, user);
        }
        return true;
    } else if (isOTPType(input.getType())) {
        UserCredentialModel otpCredential = (UserCredentialModel) input;
        // Those are not supposed to be set when calling this method in Keycloak 4.8.3 for password credential
        assertNull(otpCredential.getDevice());
        assertNull(otpCredential.getAlgorithm());
        OTPPolicy otpPolicy = session.getContext().getRealm().getOTPPolicy();
        CredentialModel newOTP = new CredentialModel();
        newOTP.setType(input.getType());
        long createdDate = Time.currentTimeMillis();
        newOTP.setCreatedDate(createdDate);
        newOTP.setValue(otpCredential.getValue());
        newOTP.setCounter(otpPolicy.getInitialCounter());
        newOTP.setDigits(otpPolicy.getDigits());
        newOTP.setAlgorithm(otpPolicy.getAlgorithm());
        newOTP.setPeriod(otpPolicy.getPeriod());
        users.get(translateUserName(user.getUsername())).otp = newOTP;
        return true;
    } else {
        log.infof("Attempt to update unsupported credential of type: %s", input.getType());
        return false;
    }
}
Also used : PasswordUserCredentialModel(org.keycloak.models.credential.PasswordUserCredentialModel) PasswordUserCredentialModel(org.keycloak.models.credential.PasswordUserCredentialModel) UserCredentialModel(org.keycloak.models.UserCredentialModel) CredentialModel(org.keycloak.credential.CredentialModel) PasswordPolicy(org.keycloak.models.PasswordPolicy) OTPPolicy(org.keycloak.models.OTPPolicy) UserCache(org.keycloak.models.cache.UserCache) PasswordUserCredentialModel(org.keycloak.models.credential.PasswordUserCredentialModel) UserCredentialModel(org.keycloak.models.UserCredentialModel) PasswordHashProvider(org.keycloak.credential.hash.PasswordHashProvider)

Example 2 with UserCache

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

the class LDAPStorageProvider method checkDNChanged.

private void checkDNChanged(RealmModel realm, UserModel local, LDAPObject ldapObject) {
    String dnFromDB = local.getFirstAttribute(LDAPConstants.LDAP_ENTRY_DN);
    String ldapDn = ldapObject.getDn().toString();
    if (!ldapDn.equals(dnFromDB)) {
        logger.debugf("Updated LDAP DN of user '%s' to '%s'", local.getUsername(), ldapDn);
        local.setSingleAttribute(LDAPConstants.LDAP_ENTRY_DN, ldapDn);
        UserCache userCache = session.userCache();
        if (userCache != null) {
            userCache.evict(realm, local);
        }
    }
}
Also used : UserCache(org.keycloak.models.cache.UserCache)

Example 3 with UserCache

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

the class PasswordCredentialProvider method createCredential.

@Override
public CredentialModel createCredential(RealmModel realm, UserModel user, PasswordCredentialModel credentialModel) {
    PasswordPolicy policy = realm.getPasswordPolicy();
    int expiredPasswordsPolicyValue = policy.getExpiredPasswords();
    // 1) create new or reset existing password
    CredentialModel createdCredential;
    CredentialModel oldPassword = getPassword(realm, user);
    if (credentialModel.getCreatedDate() == null) {
        credentialModel.setCreatedDate(Time.currentTimeMillis());
    }
    if (oldPassword == null) {
        // no password exists --> create new
        createdCredential = getCredentialStore().createCredential(realm, user, credentialModel);
    } else {
        // password exists --> update existing
        credentialModel.setId(oldPassword.getId());
        getCredentialStore().updateCredential(realm, user, credentialModel);
        createdCredential = credentialModel;
        // 2) add a password history item based on the old password
        if (expiredPasswordsPolicyValue > 1) {
            oldPassword.setId(null);
            oldPassword.setType(PasswordCredentialModel.PASSWORD_HISTORY);
            getCredentialStore().createCredential(realm, user, oldPassword);
        }
    }
    // 3) remove old password history items
    final int passwordHistoryListMaxSize = Math.max(0, expiredPasswordsPolicyValue - 1);
    getCredentialStore().getStoredCredentialsByTypeStream(realm, user, PasswordCredentialModel.PASSWORD_HISTORY).sorted(CredentialModel.comparingByStartDateDesc()).skip(passwordHistoryListMaxSize).collect(Collectors.toList()).forEach(p -> getCredentialStore().removeStoredCredential(realm, user, p.getId()));
    UserCache userCache = session.userCache();
    if (userCache != null) {
        userCache.evict(realm, user);
    }
    return createdCredential;
}
Also used : UserCredentialModel(org.keycloak.models.UserCredentialModel) PasswordCredentialModel(org.keycloak.models.credential.PasswordCredentialModel) PasswordPolicy(org.keycloak.models.PasswordPolicy) OnUserCache(org.keycloak.models.cache.OnUserCache) UserCache(org.keycloak.models.cache.UserCache)

Example 4 with UserCache

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

the class RealmAdminResource method updateRealm.

/**
 * Update the top-level information of the realm
 *
 * Any user, roles or client information in the representation
 * will be ignored.  This will only update top-level attributes of the realm.
 *
 * @param rep
 * @return
 */
@PUT
@Consumes(MediaType.APPLICATION_JSON)
public Response updateRealm(final RealmRepresentation rep) {
    auth.realm().requireManageRealm();
    logger.debug("updating realm: " + realm.getName());
    if (Config.getAdminRealm().equals(realm.getName()) && (rep.getRealm() != null && !rep.getRealm().equals(Config.getAdminRealm()))) {
        return ErrorResponse.error("Can't rename master realm", Status.BAD_REQUEST);
    }
    ReservedCharValidator.validate(rep.getRealm());
    ReservedCharValidator.validateLocales(rep.getSupportedLocales());
    try {
        if (!Constants.GENERATE.equals(rep.getPublicKey()) && (rep.getPrivateKey() != null && rep.getPublicKey() != null)) {
            try {
                KeyPairVerifier.verify(rep.getPrivateKey(), rep.getPublicKey());
            } catch (VerificationException e) {
                return ErrorResponse.error(e.getMessage(), Status.BAD_REQUEST);
            }
        }
        if (!Constants.GENERATE.equals(rep.getPublicKey()) && (rep.getCertificate() != null)) {
            try {
                X509Certificate cert = PemUtils.decodeCertificate(rep.getCertificate());
                if (cert == null) {
                    return ErrorResponse.error("Failed to decode certificate", Status.BAD_REQUEST);
                }
            } catch (Exception e) {
                return ErrorResponse.error("Failed to decode certificate", Status.BAD_REQUEST);
            }
        }
        boolean wasDuplicateEmailsAllowed = realm.isDuplicateEmailsAllowed();
        RepresentationToModel.updateRealm(rep, realm, session);
        // Refresh periodic sync tasks for configured federationProviders
        UserStorageSyncManager usersSyncManager = new UserStorageSyncManager();
        realm.getUserStorageProvidersStream().forEachOrdered(fedProvider -> usersSyncManager.notifyToRefreshPeriodicSync(session, realm, fedProvider, false));
        // This populates the map in DefaultKeycloakContext to be used when treating the event
        session.getContext().getUri();
        adminEvent.operation(OperationType.UPDATE).representation(StripSecretsUtils.strip(rep)).success();
        if (rep.isDuplicateEmailsAllowed() != null && rep.isDuplicateEmailsAllowed() != wasDuplicateEmailsAllowed) {
            UserCache cache = session.getProvider(UserCache.class);
            if (cache != null)
                cache.clear();
        }
        return Response.noContent().build();
    } catch (ModelDuplicateException e) {
        return ErrorResponse.exists("Realm with same name exists");
    } catch (ModelException e) {
        return ErrorResponse.error(e.getMessage(), Status.BAD_REQUEST);
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
        return ErrorResponse.error("Failed to update realm", Response.Status.INTERNAL_SERVER_ERROR);
    }
}
Also used : UserStorageSyncManager(org.keycloak.services.managers.UserStorageSyncManager) ModelException(org.keycloak.models.ModelException) ModelDuplicateException(org.keycloak.models.ModelDuplicateException) VerificationException(org.keycloak.common.VerificationException) UserCache(org.keycloak.models.cache.UserCache) X509Certificate(java.security.cert.X509Certificate) ModelDuplicateException(org.keycloak.models.ModelDuplicateException) BadRequestException(javax.ws.rs.BadRequestException) ParseException(java.text.ParseException) VerificationException(org.keycloak.common.VerificationException) NotFoundException(javax.ws.rs.NotFoundException) ModelException(org.keycloak.models.ModelException) Consumes(javax.ws.rs.Consumes) PUT(javax.ws.rs.PUT)

Example 5 with UserCache

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

the class LDAPSyncTest method test09MembershipUsingDifferentAttributes.

// KEYCLOAK-14696
@Test
public void test09MembershipUsingDifferentAttributes() throws Exception {
    final Map<String, String> previousConf = testingClient.server().fetch(session -> {
        LDAPTestContext ctx = LDAPTestContext.init(session);
        RealmModel appRealm = ctx.getRealm();
        // 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);
        });
        Map<String, String> orig = new HashMap<>();
        orig.put(LDAPConstants.RDN_LDAP_ATTRIBUTE, ctx.getLdapModel().getConfig().getFirst(LDAPConstants.RDN_LDAP_ATTRIBUTE));
        orig.put(LDAPConstants.USERS_DN, ctx.getLdapModel().getConfig().getFirst(LDAPConstants.USERS_DN));
        orig.put(LDAPConstants.USERNAME_LDAP_ATTRIBUTE, ctx.getLdapModel().getConfig().getFirst(LDAPConstants.USERNAME_LDAP_ATTRIBUTE));
        // create an OU and this test will work below it, set RDN to CN and username to uid/samaccountname
        LDAPTestUtils.addLdapOU(ctx.getLdapProvider(), "KC14696");
        ctx.getLdapModel().getConfig().putSingle(LDAPConstants.USERS_DN, "ou=KC14696," + orig.get(LDAPConstants.USERS_DN));
        ctx.getLdapModel().getConfig().putSingle(LDAPConstants.RDN_LDAP_ATTRIBUTE, LDAPConstants.CN);
        ctx.getLdapModel().getConfig().putSingle(LDAPConstants.USERNAME_LDAP_ATTRIBUTE, ctx.getLdapProvider().getLdapIdentityStore().getConfig().isActiveDirectory() ? LDAPConstants.SAM_ACCOUNT_NAME : LDAPConstants.UID);
        ctx.getRealm().updateComponent(ctx.getLdapModel());
        ComponentModel mapperModel = LDAPTestUtils.getSubcomponentByName(appRealm, ctx.getLdapModel(), "username");
        mapperModel.getConfig().putSingle(UserAttributeLDAPStorageMapper.LDAP_ATTRIBUTE, ctx.getLdapProvider().getLdapIdentityStore().getConfig().isActiveDirectory() ? LDAPConstants.SAM_ACCOUNT_NAME : LDAPConstants.UID);
        ctx.getRealm().updateComponent(mapperModel);
        LDAPTestUtils.addUserAttributeMapper(appRealm, LDAPTestUtils.getLdapProviderModel(appRealm), "cnMapper", "firstName", LDAPConstants.CN);
        return orig;
    }, Map.class);
    testingClient.server().run(session -> {
        LDAPTestContext ctx = LDAPTestContext.init(session);
        RealmModel appRealm = ctx.getRealm();
        // create a user8 inside the usersDn
        LDAPObject user8 = LDAPTestUtils.addLDAPUser(ctx.getLdapProvider(), ctx.getRealm(), "user8", "User8FN", "User8LN", "user8@email.org", "user8street", "126");
        // create a sample ou inside usersDn
        LDAPTestUtils.addLdapOU(ctx.getLdapProvider(), "sample-org");
        // create a user below the sample org with the same common-name but different username
        String usersDn = ctx.getLdapModel().get(LDAPConstants.USERS_DN);
        ctx.getLdapModel().getConfig().putSingle(LDAPConstants.USERS_DN, "ou=sample-org," + usersDn);
        ctx.getRealm().updateComponent(ctx.getLdapModel());
        LDAPTestUtils.addLDAPUser(ctx.getLdapProvider(), ctx.getRealm(), "user8bis", "User8FN", "User8LN", "user8bis@email.org", "user8street", "126");
        // get back to parent usersDn
        ctx.getLdapModel().getConfig().putSingle(LDAPConstants.USERS_DN, usersDn);
        ctx.getRealm().updateComponent(ctx.getLdapModel());
        // create a group with user8 as a member
        String descriptionAttrName = LDAPTestUtils.getGroupDescriptionLDAPAttrName(ctx.getLdapProvider());
        LDAPObject user8Group = LDAPTestUtils.createLDAPGroup(session, appRealm, ctx.getLdapModel(), "user8group", descriptionAttrName, "user8group - description");
        LDAPUtils.addMember(ctx.getLdapProvider(), MembershipType.DN, LDAPConstants.MEMBER, "not-used", user8Group, user8);
    });
    testingClient.server().run(session -> {
        LDAPTestContext ctx = LDAPTestContext.init(session);
        KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
        SynchronizationResult syncResult = new UserStorageSyncManager().syncAllUsers(sessionFactory, "test", ctx.getLdapModel());
        Assert.assertEquals(2, syncResult.getAdded());
    });
    testingClient.server().run(session -> {
        LDAPTestContext ctx = LDAPTestContext.init(session);
        RealmModel appRealm = ctx.getRealm();
        GroupModel user8Group = KeycloakModelUtils.findGroupByPath(appRealm, "/user8group");
        Assert.assertNotNull(user8Group);
        UserModel user8 = session.users().getUserByUsername(appRealm, "user8");
        Assert.assertNotNull(user8);
        UserModel user8Bis = session.users().getUserByUsername(appRealm, "user8bis");
        Assert.assertNotNull(user8Bis);
        Assert.assertTrue("User user8 contains the group", user8.getGroupsStream().collect(Collectors.toSet()).contains(user8Group));
        Assert.assertFalse("User user8bis does not contain the group", user8Bis.getGroupsStream().collect(Collectors.toSet()).contains(user8Group));
        List<String> members = session.users().getGroupMembersStream(appRealm, user8Group).map(u -> u.getUsername()).collect(Collectors.toList());
        Assert.assertEquals("Group contains only user8", members, Collections.singletonList("user8"));
    });
    // revert changes
    testingClient.server().run(session -> {
        LDAPTestContext ctx = LDAPTestContext.init(session);
        RealmModel appRealm = ctx.getRealm();
        session.users().removeImportedUsers(appRealm, ldapModelId);
        LDAPTestUtils.removeLDAPUserByUsername(ctx.getLdapProvider(), appRealm, ctx.getLdapProvider().getLdapIdentityStore().getConfig(), "user8");
        LDAPTestUtils.removeLDAPUserByUsername(ctx.getLdapProvider(), appRealm, ctx.getLdapProvider().getLdapIdentityStore().getConfig(), "user8bis");
        LDAPObject ou = new LDAPObject();
        ou.setDn(LDAPDn.fromString("ou=sample-org,ou=KC14696," + previousConf.get(LDAPConstants.USERS_DN)));
        ctx.getLdapProvider().getLdapIdentityStore().remove(ou);
        ou.setDn(LDAPDn.fromString("ou=KC14696," + previousConf.get(LDAPConstants.USERS_DN)));
        ctx.getLdapProvider().getLdapIdentityStore().remove(ou);
        for (Map.Entry<String, String> e : previousConf.entrySet()) {
            if (e.getValue() == null) {
                ctx.getLdapModel().getConfig().remove(e.getKey());
            } else {
                ctx.getLdapModel().getConfig().putSingle(e.getKey(), e.getValue());
            }
        }
        ctx.getRealm().updateComponent(ctx.getLdapModel());
        ComponentModel cnMapper = LDAPTestUtils.getSubcomponentByName(ctx.getRealm(), ctx.getLdapModel(), "cnMapper");
        ctx.getRealm().removeComponent(cnMapper);
        ComponentModel mapperModel = LDAPTestUtils.getSubcomponentByName(appRealm, ctx.getLdapModel(), "username");
        mapperModel.getConfig().putSingle(UserAttributeLDAPStorageMapper.LDAP_ATTRIBUTE, ctx.getLdapProvider().getLdapIdentityStore().getConfig().getUsernameLdapAttribute());
        ctx.getRealm().updateComponent(mapperModel);
    });
}
Also used : MethodSorters(org.junit.runners.MethodSorters) LDAPStorageProvider(org.keycloak.storage.ldap.LDAPStorageProvider) KeycloakModelUtils(org.keycloak.models.utils.KeycloakModelUtils) HashMap(java.util.HashMap) SynchronizationResultRepresentation(org.keycloak.representations.idm.SynchronizationResultRepresentation) LDAPConstants(org.keycloak.models.LDAPConstants) ComponentRepresentation(org.keycloak.representations.idm.ComponentRepresentation) UserModel(org.keycloak.models.UserModel) LDAPRule(org.keycloak.testsuite.util.LDAPRule) Map(java.util.Map) ComponentModel(org.keycloak.component.ComponentModel) GroupModel(org.keycloak.models.GroupModel) BadRequestException(javax.ws.rs.BadRequestException) ClassRule(org.junit.ClassRule) LDAPGroupMapperMode(org.keycloak.storage.ldap.mappers.membership.LDAPGroupMapperMode) LDAPDn(org.keycloak.storage.ldap.idm.model.LDAPDn) MembershipType(org.keycloak.storage.ldap.mappers.membership.MembershipType) WaitUtils(org.keycloak.testsuite.util.WaitUtils) RealmModel(org.keycloak.models.RealmModel) LDAPTestUtils(org.keycloak.testsuite.util.LDAPTestUtils) Matchers(org.hamcrest.Matchers) Test(org.junit.Test) LDAPStorageProviderFactory(org.keycloak.storage.ldap.LDAPStorageProviderFactory) GroupLDAPStorageMapperFactory(org.keycloak.storage.ldap.mappers.membership.group.GroupLDAPStorageMapperFactory) Collectors(java.util.stream.Collectors) GroupLDAPStorageMapper(org.keycloak.storage.ldap.mappers.membership.group.GroupLDAPStorageMapper) UserStorageSyncManager(org.keycloak.services.managers.UserStorageSyncManager) LDAPObject(org.keycloak.storage.ldap.idm.model.LDAPObject) UserProvider(org.keycloak.models.UserProvider) List(java.util.List) UserCache(org.keycloak.models.cache.UserCache) UserAttributeLDAPStorageMapper(org.keycloak.storage.ldap.mappers.UserAttributeLDAPStorageMapper) LDAPUtils(org.keycloak.storage.ldap.LDAPUtils) KeycloakSessionFactory(org.keycloak.models.KeycloakSessionFactory) SynchronizationResult(org.keycloak.storage.user.SynchronizationResult) Assert(org.junit.Assert) FixMethodOrder(org.junit.FixMethodOrder) Collections(java.util.Collections) GroupMapperConfig(org.keycloak.storage.ldap.mappers.membership.group.GroupMapperConfig) UserStorageSyncManager(org.keycloak.services.managers.UserStorageSyncManager) HashMap(java.util.HashMap) GroupModel(org.keycloak.models.GroupModel) UserCache(org.keycloak.models.cache.UserCache) KeycloakSessionFactory(org.keycloak.models.KeycloakSessionFactory) RealmModel(org.keycloak.models.RealmModel) UserModel(org.keycloak.models.UserModel) ComponentModel(org.keycloak.component.ComponentModel) LDAPObject(org.keycloak.storage.ldap.idm.model.LDAPObject) SynchronizationResult(org.keycloak.storage.user.SynchronizationResult) HashMap(java.util.HashMap) Map(java.util.Map) Test(org.junit.Test)

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