Skip to content

Commit

Permalink
KEYCLOAK-5662 - CachePolicy.MAX_LIFESPAN - Cached LDAP users aren't b…
Browse files Browse the repository at this point in the history
…eing refreshed at all
  • Loading branch information
Przemysław Kadej committed Nov 13, 2017
1 parent ab8f472 commit e28f402
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,9 @@ protected UserModel validateCache(RealmModel realm, CachedUser cached) {
return null;
}

StorageId storageId = new StorageId(cached.getId());
StorageId storageId = cached.getFederationLink() != null ?
new StorageId(cached.getFederationLink(), cached.getId()) : new StorageId(cached.getId());

if (!storageId.isLocal()) {
ComponentModel component = realm.getComponent(storageId.getProviderId());
UserStorageProviderModel model = new UserStorageProviderModel(component);
Expand Down Expand Up @@ -336,7 +338,8 @@ protected UserModel validateCache(RealmModel realm, CachedUser cached) {
protected UserModel cacheUser(RealmModel realm, UserModel delegate, Long revision) {
int notBefore = getDelegate().getNotBeforeOfUser(realm, delegate);

StorageId storageId = new StorageId(delegate.getId());
StorageId storageId = delegate.getFederationLink() != null ?
new StorageId(delegate.getFederationLink(), delegate.getId()) : new StorageId(delegate.getId());
CachedUser cached = null;
if (!storageId.isLocal()) {
ComponentModel component = realm.getComponent(storageId.getProviderId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.jboss.logging.Logger;
import org.junit.Assert;
import org.junit.Before;
Expand All @@ -38,6 +39,7 @@
import org.keycloak.OAuth2Constants;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.common.util.Time;
import org.keycloak.component.ComponentModel;
import org.keycloak.credential.CredentialModel;
import org.keycloak.models.Constants;
Expand All @@ -48,6 +50,7 @@
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.cache.CachedUserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.AccessToken;
import org.keycloak.services.managers.RealmManager;
Expand Down Expand Up @@ -193,6 +196,13 @@ public void testSyncRegistrationOff() {
@Before
public void onBefore() {
adminClient = Keycloak.getInstance(AUTH_SERVER_ROOT, MASTER, ADMIN, ADMIN, Constants.ADMIN_CLI_CLIENT_ID);
UserStorageProviderModel model = new UserStorageProviderModel(ldapModel);
model.setCachePolicy(UserStorageProviderModel.CachePolicy.MAX_LIFESPAN);
model.setMaxLifespan(600000); // Lifetime is 10 minutes
KeycloakSession session = keycloakRule.startSession();
RealmModel realm = session.realms().getRealmByName("test");
realm.updateComponent(model);
keycloakRule.stopSession(session, true);
}

@Test
Expand Down Expand Up @@ -1131,4 +1141,107 @@ public void testSearchByAttributes() {
}
}

@Test
public void testLDAPUserRefreshCache() {
KeycloakSession session = keycloakRule.startSession();

try {
RealmModel appRealm = new RealmManager(session).getRealmByName("test");

LDAPStorageProvider ldapProvider = LDAPTestUtils.getLdapProvider(session, ldapModel);
LDAPTestUtils.addLDAPUser(ldapProvider, appRealm, "johndirect", "John", "Direct", "johndirect@email.org", null, "1234");

// Fetch user from LDAP and check that postalCode is filled
UserModel user = session.users().getUserByUsername("johndirect", appRealm);
String postalCode = user.getFirstAttribute("postal_code");
Assert.assertEquals("1234", postalCode);

LDAPTestUtils.removeLDAPUserByUsername(ldapProvider, appRealm, ldapProvider.getLdapIdentityStore().getConfig(), "johndirect");
} finally {
keycloakRule.stopSession(session, true);
}

Time.setOffset(60 * 5); // 5 minutes in future, user should be cached still
session = keycloakRule.startSession();
try {
RealmModel appRealm = new RealmManager(session).getRealmByName("test");
CachedUserModel user = (CachedUserModel) session.users().getUserByUsername("johndirect", appRealm);
String postalCode = user.getFirstAttribute("postal_code");
String email = user.getEmail();
Assert.assertEquals("1234", postalCode);
Assert.assertEquals("johndirect@email.org", email);
} finally {
keycloakRule.stopSession(session, true);
}

Time.setOffset(60 * 20); // 20 minutes into future, cache will be invalidated
session = keycloakRule.startSession();
try {
RealmModel appRealm = new RealmManager(session).getRealmByName("test");
UserModel user = session.users().getUserByUsername("johndirect", appRealm);
Assert.assertNull(user);
} finally {
keycloakRule.stopSession(session, true);
Time.setOffset(0);
}
}

@Test
public void testCacheUser() {
UserStorageProviderModel model = new UserStorageProviderModel(ldapModel);
model.setCachePolicy(UserStorageProviderModel.CachePolicy.NO_CACHE);
KeycloakSession session = keycloakRule.startSession();
RealmModel appRealm = session.realms().getRealmByName("test");
appRealm.updateComponent(model);

String userId = null;
UserModel testedUser = null;
try {
LDAPStorageProvider ldapProvider = LDAPTestUtils.getLdapProvider(session, ldapModel);
LDAPTestUtils.addLDAPUser(ldapProvider, appRealm, "testCacheUser", "John", "Cached", "johndirect@test.com", null, "1234");

// Fetch user from LDAP and check that postalCode is filled
testedUser = session.users().getUserByUsername("testCacheUser", appRealm);
userId = testedUser.getId();

Assert.assertNotNull(userId);
Assert.assertTrue(StringUtils.isNotBlank(userId));

} finally {
keycloakRule.stopSession(session, true);
}

session = keycloakRule.startSession();
appRealm = session.realms().getRealmByName("test");

testedUser = session.users().getUserById(userId, appRealm);
Assert.assertFalse(testedUser instanceof CachedUserModel);
keycloakRule.stopSession(session, false);

// restore default cache policy
onBefore();

session = keycloakRule.startSession();
appRealm = session.realms().getRealmByName("test");
// initial get for cache
testedUser = session.users().getUserById(userId, appRealm);
Assert.assertTrue(testedUser instanceof CachedUserModel);
keycloakRule.stopSession(session, false);

Time.setOffset(60 * 5); // 5 minutes in future, should be cached still
session = keycloakRule.startSession();
appRealm = session.realms().getRealmByName("test");
testedUser = session.users().getUserById(userId, appRealm);
Assert.assertTrue(testedUser instanceof CachedUserModel);
keycloakRule.stopSession(session, false);

Time.setOffset(60 * 10); // 10 minutes into future, cache will be invalidated
session = keycloakRule.startSession();
appRealm = session.realms().getRealmByName("test");
testedUser = session.users().getUserByUsername("thor", appRealm);
Assert.assertFalse(testedUser instanceof CachedUserModel);
keycloakRule.stopSession(session, false);

Time.setOffset(0);
}
}

0 comments on commit e28f402

Please sign in to comment.