Search in sources :

Example 1 with CachedUserModel

use of org.keycloak.models.cache.CachedUserModel 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;
}
Also used : CachedUserModel(org.keycloak.models.cache.CachedUserModel) UserModel(org.keycloak.models.UserModel) ReadOnlyUserModelDelegate(org.keycloak.models.utils.ReadOnlyUserModelDelegate) LDAPStorageMapper(org.keycloak.storage.ldap.mappers.LDAPStorageMapper) ModelException(org.keycloak.models.ModelException) CachedUserModel(org.keycloak.models.cache.CachedUserModel) AtomicReference(java.util.concurrent.atomic.AtomicReference) UpdateOnlyChangeUserModelDelegate(org.keycloak.storage.adapter.UpdateOnlyChangeUserModelDelegate)

Example 2 with CachedUserModel

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

the class UserStorageFailureTest method testKeycloak5926.

@Test
public void testKeycloak5926() {
    oauth.clientId("test-app");
    oauth.redirectUri(OAuthClient.APP_AUTH_ROOT);
    // make sure local copy is deleted
    testingClient.server().run(session -> {
        RealmModel realm = session.realms().getRealmByName(AuthRealm.TEST);
        UserModel user = session.userLocalStorage().getUserByUsername(realm, FailableHardcodedStorageProvider.username);
        if (user != null) {
            session.userLocalStorage().removeUser(realm, user);
        }
    });
    // query user to make sure its imported
    testingClient.server().run(session -> {
        RealmModel realm = session.realms().getRealmByName(AuthRealm.TEST);
        UserModel user = session.users().getUserByUsername(realm, FailableHardcodedStorageProvider.username);
        Assert.assertNotNull(user);
    });
    evictUser(FailableHardcodedStorageProvider.username);
    evictUser(LOCAL_USER);
    toggleForceFail(true);
    testingClient.server().run(session -> {
        RealmModel realm = session.realms().getRealmByName(AuthRealm.TEST);
        UserModel local = session.users().getUserByUsername(realm, LOCAL_USER);
        Assert.assertNotNull(local);
        // assert that lookup of user storage user fails
        try {
            UserModel user = session.users().getUserByUsername(realm, FailableHardcodedStorageProvider.username);
            Assert.fail();
        } catch (Exception e) {
            Assert.assertEquals("FORCED FAILURE", e.getMessage());
        }
    });
    // test that we can still login to a user
    loginSuccessAndLogout("test-user@localhost", "password");
    toggleProviderEnabled(false);
    testingClient.server().run(session -> {
        RealmModel realm = session.realms().getRealmByName(AuthRealm.TEST);
        UserModel local = session.users().getUserByUsername(realm, LOCAL_USER);
        Assert.assertNotNull(local);
        Stream<UserModel> result;
        result = session.users().searchForUserStream(realm, LOCAL_USER);
        Assert.assertEquals(1, result.count());
        result = session.users().searchForUserStream(realm, FailableHardcodedStorageProvider.username);
        Assert.assertEquals(1, result.count());
        result = session.users().searchForUserStream(realm, LOCAL_USER, 0, 2);
        Assert.assertEquals(1, result.count());
        result = session.users().searchForUserStream(realm, FailableHardcodedStorageProvider.username, 0, 2);
        Assert.assertEquals(1, result.count());
        Map<String, String> localParam = new HashMap<>();
        localParam.put("username", LOCAL_USER);
        Map<String, String> hardcodedParam = new HashMap<>();
        hardcodedParam.put("username", FailableHardcodedStorageProvider.username);
        result = session.users().searchForUserStream(realm, localParam);
        Assert.assertEquals(1, result.count());
        result = session.users().searchForUserStream(realm, hardcodedParam);
        Assert.assertEquals(1, result.count());
        result = session.users().searchForUserStream(realm, localParam, 0, 2);
        Assert.assertEquals(1, result.count());
        result = session.users().searchForUserStream(realm, hardcodedParam, 0, 2);
        Assert.assertEquals(1, result.count());
        // we run a terminal operation on the stream to make sure it is consumed.
        session.users().getUsersStream(realm).count();
        session.users().getUsersCount(realm);
        UserModel user = session.users().getUserByUsername(realm, FailableHardcodedStorageProvider.username);
        Assert.assertFalse(user instanceof CachedUserModel);
        Assert.assertEquals(FailableHardcodedStorageProvider.username, user.getUsername());
        Assert.assertEquals(FailableHardcodedStorageProvider.email, user.getEmail());
        Assert.assertFalse(user.isEnabled());
        try {
            user.setEmail("error@error.com");
            Assert.fail();
        } catch (Exception ex) {
        }
    });
    // make sure user isn't cached as provider is disabled
    testingClient.server().run(session -> {
        RealmModel realm = session.realms().getRealmByName(AuthRealm.TEST);
        UserModel user = session.users().getUserByUsername(realm, FailableHardcodedStorageProvider.username);
        Assert.assertFalse(user instanceof CachedUserModel);
        Assert.assertEquals(FailableHardcodedStorageProvider.username, user.getUsername());
        Assert.assertEquals(FailableHardcodedStorageProvider.email, user.getEmail());
    });
    // make ABSOLUTELY sure user isn't cached as provider is disabled
    testingClient.server().run(session -> {
        RealmModel realm = session.realms().getRealmByName(AuthRealm.TEST);
        UserModel user = session.users().getUserByUsername(realm, FailableHardcodedStorageProvider.username);
        Assert.assertFalse(user instanceof CachedUserModel);
        Assert.assertEquals(FailableHardcodedStorageProvider.username, user.getUsername());
        Assert.assertEquals(FailableHardcodedStorageProvider.email, user.getEmail());
    });
    toggleProviderEnabled(true);
    toggleForceFail(false);
    // user should be cachable now
    testingClient.server().run(session -> {
        RealmModel realm = session.realms().getRealmByName(AuthRealm.TEST);
        UserModel user = session.users().getUserByUsername(realm, FailableHardcodedStorageProvider.username);
        Assert.assertTrue(user instanceof CachedUserModel);
        Assert.assertEquals(FailableHardcodedStorageProvider.username, user.getUsername());
        Assert.assertEquals(FailableHardcodedStorageProvider.email, user.getEmail());
    });
    events.clear();
}
Also used : RealmModel(org.keycloak.models.RealmModel) UserModel(org.keycloak.models.UserModel) CachedUserModel(org.keycloak.models.cache.CachedUserModel) HashMap(java.util.HashMap) MultivaluedHashMap(org.keycloak.common.util.MultivaluedHashMap) CachedUserModel(org.keycloak.models.cache.CachedUserModel) Test(org.junit.Test) AbstractTestRealmKeycloakTest(org.keycloak.testsuite.AbstractTestRealmKeycloakTest)

Example 3 with CachedUserModel

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

the class UserStorageTest method testMaxLifespan.

@Test
public void testMaxLifespan() {
    ApiUtil.findUserByUsername(testRealmResource(), "thor");
    // set eviction to 1 hour from now
    ComponentRepresentation propProviderRW = testRealmResource().components().component(propProviderRWId).toRepresentation();
    propProviderRW.getConfig().putSingle(CACHE_POLICY, CachePolicy.MAX_LIFESPAN.name());
    // 1 hour in milliseconds
    propProviderRW.getConfig().putSingle(MAX_LIFESPAN, Long.toString(1 * 60 * 60 * 1000));
    testRealmResource().components().component(propProviderRWId).update(propProviderRW);
    // now
    testingClient.server().run(session -> {
        RealmModel realm = session.realms().getRealmByName("test");
        UserModel user = session.users().getUserByUsername(realm, "thor");
        System.out.println("User class: " + user.getClass());
        // should still be cached
        Assert.assertTrue(user instanceof CachedUserModel);
    });
    // 1/2 hour in future
    setTimeOffset(1 / 2 * 60 * 60);
    testingClient.server().run(session -> {
        RealmModel realm = session.realms().getRealmByName("test");
        UserModel user = session.users().getUserByUsername(realm, "thor");
        System.out.println("User class: " + user.getClass());
        // should still be cached
        Assert.assertTrue(user instanceof CachedUserModel);
    });
    // 2 hours in future
    setTimeOffset(2 * 60 * 60);
    testingClient.server().run(session -> {
        RealmModel realm = session.realms().getRealmByName("test");
        UserModel user = session.users().getUserByUsername(realm, "thor");
        System.out.println("User class: " + user.getClass());
        // should be evicted
        Assert.assertFalse(user instanceof CachedUserModel);
    });
}
Also used : ComponentRepresentation(org.keycloak.representations.idm.ComponentRepresentation) RealmModel(org.keycloak.models.RealmModel) CachedUserModel(org.keycloak.models.cache.CachedUserModel) UserModel(org.keycloak.models.UserModel) CachedUserModel(org.keycloak.models.cache.CachedUserModel) ModelTest(org.keycloak.testsuite.arquillian.annotation.ModelTest) AbstractAuthTest(org.keycloak.testsuite.AbstractAuthTest) Test(org.junit.Test)

Example 4 with CachedUserModel

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

the class UserStorageTest method testNoCache.

@Test
public void testNoCache() {
    ApiUtil.findUserByUsername(testRealmResource(), "thor");
    // set NO_CACHE policy
    ComponentRepresentation propProviderRW = testRealmResource().components().component(propProviderRWId).toRepresentation();
    propProviderRW.getConfig().putSingle(CACHE_POLICY, CachePolicy.NO_CACHE.name());
    testRealmResource().components().component(propProviderRWId).update(propProviderRW);
    testingClient.server().run(session -> {
        RealmModel realm = session.realms().getRealmByName("test");
        UserModel user = session.users().getUserByUsername(realm, "thor");
        System.out.println("User class: " + user.getClass());
        // should be evicted
        Assert.assertFalse(user instanceof CachedUserModel);
    });
    testingClient.server().run(session -> {
        RealmModel realm = session.realms().getRealmByName("test");
        UserModel thor2 = session.users().getUserByUsername(realm, "thor");
        Assert.assertFalse(thor2 instanceof CachedUserModel);
    });
    propProviderRW = testRealmResource().components().component(propProviderRWId).toRepresentation();
    propProviderRW.getConfig().putSingle(CACHE_POLICY, CachePolicy.DEFAULT.name());
    propProviderRW.getConfig().remove("evictionHour");
    propProviderRW.getConfig().remove("evictionMinute");
    propProviderRW.getConfig().remove("evictionDay");
    testRealmResource().components().component(propProviderRWId).update(propProviderRW);
    testingClient.server().run(session -> {
        RealmModel realm = session.realms().getRealmByName("test");
        UserModel thor = session.users().getUserByUsername(realm, "thor");
        System.out.println("Foo");
    });
}
Also used : ComponentRepresentation(org.keycloak.representations.idm.ComponentRepresentation) RealmModel(org.keycloak.models.RealmModel) CachedUserModel(org.keycloak.models.cache.CachedUserModel) UserModel(org.keycloak.models.UserModel) CachedUserModel(org.keycloak.models.cache.CachedUserModel) ModelTest(org.keycloak.testsuite.arquillian.annotation.ModelTest) AbstractAuthTest(org.keycloak.testsuite.AbstractAuthTest) Test(org.junit.Test)

Example 5 with CachedUserModel

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

the class LDAPProvidersIntegrationTest method testCacheUser.

@Test
public void testCacheUser() {
    String userId = testingClient.server().fetch(session -> {
        LDAPTestContext ctx = LDAPTestContext.init(session);
        ctx.getLdapModel().setCachePolicy(UserStorageProviderModel.CachePolicy.NO_CACHE);
        ctx.getRealm().updateComponent(ctx.getLdapModel());
        LDAPTestUtils.addLDAPUser(ctx.getLdapProvider(), ctx.getRealm(), "testCacheUser", "John", "Cached", "johndirect@test.com", null, "1234");
        // Fetch user from LDAP and check that postalCode is filled
        UserModel testedUser = session.users().getUserByUsername(ctx.getRealm(), "testCacheUser");
        String usserId = testedUser.getId();
        Assert.assertNotNull(usserId);
        Assert.assertFalse(usserId.isEmpty());
        return usserId;
    }, String.class);
    testingClient.server().run(session -> {
        RealmModel appRealm = session.realms().getRealmByName(TEST_REALM_NAME);
        UserModel testedUser = session.users().getUserById(appRealm, userId);
        Assert.assertFalse(testedUser instanceof CachedUserModel);
    });
    // restore default cache policy
    testingClient.server().run(session -> {
        LDAPTestContext ctx = LDAPTestContext.init(session);
        ctx.getLdapModel().setCachePolicy(UserStorageProviderModel.CachePolicy.MAX_LIFESPAN);
        // Lifetime is 10 minutes
        ctx.getLdapModel().setMaxLifespan(600000);
        ctx.getRealm().updateComponent(ctx.getLdapModel());
    });
    testingClient.server().run(session -> {
        RealmModel appRealm = session.realms().getRealmByName(TEST_REALM_NAME);
        UserModel testedUser = session.users().getUserById(appRealm, userId);
        Assert.assertTrue(testedUser instanceof CachedUserModel);
    });
    // 5 minutes in future, should be cached still
    setTimeOffset(60 * 5);
    testingClient.server().run(session -> {
        RealmModel appRealm = session.realms().getRealmByName(TEST_REALM_NAME);
        UserModel testedUser = session.users().getUserById(appRealm, userId);
        Assert.assertTrue(testedUser instanceof CachedUserModel);
    });
    // 10 minutes into future, cache will be invalidated
    setTimeOffset(60 * 10);
    testingClient.server().run(session -> {
        RealmModel appRealm = session.realms().getRealmByName(TEST_REALM_NAME);
        UserModel testedUser = session.users().getUserByUsername(appRealm, "thor");
        Assert.assertFalse(testedUser instanceof CachedUserModel);
    });
    setTimeOffset(0);
}
Also used : CachedUserModel(org.keycloak.models.cache.CachedUserModel) UserModel(org.keycloak.models.UserModel) RealmModel(org.keycloak.models.RealmModel) CachedUserModel(org.keycloak.models.cache.CachedUserModel) AbstractAuthTest(org.keycloak.testsuite.AbstractAuthTest) Test(org.junit.Test)

Aggregations

CachedUserModel (org.keycloak.models.cache.CachedUserModel)9 UserModel (org.keycloak.models.UserModel)8 Test (org.junit.Test)7 RealmModel (org.keycloak.models.RealmModel)7 AbstractAuthTest (org.keycloak.testsuite.AbstractAuthTest)6 ModelTest (org.keycloak.testsuite.arquillian.annotation.ModelTest)4 ComponentRepresentation (org.keycloak.representations.idm.ComponentRepresentation)3 Calendar (java.util.Calendar)1 HashMap (java.util.HashMap)1 AtomicReference (java.util.concurrent.atomic.AtomicReference)1 MultivaluedHashMap (org.keycloak.common.util.MultivaluedHashMap)1 ModelException (org.keycloak.models.ModelException)1 UserCredentialModel (org.keycloak.models.UserCredentialModel)1 PasswordCredentialModel (org.keycloak.models.credential.PasswordCredentialModel)1 ReadOnlyUserModelDelegate (org.keycloak.models.utils.ReadOnlyUserModelDelegate)1 RealmManager (org.keycloak.services.managers.RealmManager)1 UpdateOnlyChangeUserModelDelegate (org.keycloak.storage.adapter.UpdateOnlyChangeUserModelDelegate)1 LDAPStorageProvider (org.keycloak.storage.ldap.LDAPStorageProvider)1 LDAPStorageMapper (org.keycloak.storage.ldap.mappers.LDAPStorageMapper)1 AbstractTestRealmKeycloakTest (org.keycloak.testsuite.AbstractTestRealmKeycloakTest)1