Skip to content

Commit

Permalink
Merge pull request keycloak#4818 from patriot1burke/master
Browse files Browse the repository at this point in the history
KEYCLOAK-5926
  • Loading branch information
patriot1burke authored Dec 8, 2017
2 parents 00fb364 + fce16fe commit 5d5a200
Show file tree
Hide file tree
Showing 16 changed files with 530 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import org.keycloak.models.cache.infinispan.events.UserFederationLinkUpdatedEvent;
import org.keycloak.models.cache.infinispan.events.UserFullInvalidationEvent;
import org.keycloak.models.cache.infinispan.events.UserUpdatedEvent;
import org.keycloak.models.utils.ReadOnlyUserModelDelegate;
import org.keycloak.storage.StorageId;
import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.UserStorageProviderModel;
Expand Down Expand Up @@ -296,36 +297,41 @@ protected UserModel validateCache(RealmModel realm, CachedUser cached) {
if (!storageId.isLocal()) {
ComponentModel component = realm.getComponent(storageId.getProviderId());
UserStorageProviderModel model = new UserStorageProviderModel(component);
UserStorageProviderModel.CachePolicy policy = model.getCachePolicy();

// although we do set a timeout, Infinispan has no guarantees when the user will be evicted
// its also hard to test stuff
boolean invalidate = false;
if (policy != null) {
//String currentTime = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(new Date(Time.currentTimeMillis()));
if (policy == UserStorageProviderModel.CachePolicy.NO_CACHE) {
invalidate = true;
} else if (cached.getCacheTimestamp() < model.getCacheInvalidBefore()) {
invalidate = true;
} else if (policy == UserStorageProviderModel.CachePolicy.MAX_LIFESPAN) {
if (cached.getCacheTimestamp() + model.getMaxLifespan() < Time.currentTimeMillis()) {
if (!model.isEnabled()) {
invalidate = true;
} else {
UserStorageProviderModel.CachePolicy policy = model.getCachePolicy();
if (policy != null) {
//String currentTime = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(new Date(Time.currentTimeMillis()));
if (policy == UserStorageProviderModel.CachePolicy.NO_CACHE) {
invalidate = true;
}
} else if (policy == UserStorageProviderModel.CachePolicy.EVICT_DAILY) {
long dailyTimeout = dailyTimeout(model.getEvictionHour(), model.getEvictionMinute());
dailyTimeout = dailyTimeout - (24 * 60 * 60 * 1000);
//String timeout = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(new Date(dailyTimeout));
//String stamp = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(new Date(cached.getCacheTimestamp()));
if (cached.getCacheTimestamp() <= dailyTimeout) {
invalidate = true;
}
} else if (policy == UserStorageProviderModel.CachePolicy.EVICT_WEEKLY) {
int oneWeek = 7 * 24 * 60 * 60 * 1000;
long weeklyTimeout = weeklyTimeout(model.getEvictionDay(), model.getEvictionHour(), model.getEvictionMinute());
long lastTimeout = weeklyTimeout - oneWeek;
//String timeout = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(new Date(weeklyTimeout));
//String stamp = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(new Date(cached.getCacheTimestamp()));
if (cached.getCacheTimestamp() <= lastTimeout) {
} else if (cached.getCacheTimestamp() < model.getCacheInvalidBefore()) {
invalidate = true;
} else if (policy == UserStorageProviderModel.CachePolicy.MAX_LIFESPAN) {
if (cached.getCacheTimestamp() + model.getMaxLifespan() < Time.currentTimeMillis()) {
invalidate = true;
}
} else if (policy == UserStorageProviderModel.CachePolicy.EVICT_DAILY) {
long dailyTimeout = dailyTimeout(model.getEvictionHour(), model.getEvictionMinute());
dailyTimeout = dailyTimeout - (24 * 60 * 60 * 1000);
//String timeout = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(new Date(dailyTimeout));
//String stamp = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(new Date(cached.getCacheTimestamp()));
if (cached.getCacheTimestamp() <= dailyTimeout) {
invalidate = true;
}
} else if (policy == UserStorageProviderModel.CachePolicy.EVICT_WEEKLY) {
int oneWeek = 7 * 24 * 60 * 60 * 1000;
long weeklyTimeout = weeklyTimeout(model.getEvictionDay(), model.getEvictionHour(), model.getEvictionMinute());
long lastTimeout = weeklyTimeout - oneWeek;
//String timeout = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(new Date(weeklyTimeout));
//String stamp = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL).format(new Date(cached.getCacheTimestamp()));
if (cached.getCacheTimestamp() <= lastTimeout) {
invalidate = true;
}
}
}
}
Expand All @@ -346,6 +352,14 @@ protected UserModel cacheUser(RealmModel realm, UserModel delegate, Long revisio
if (!storageId.isLocal()) {
ComponentModel component = realm.getComponent(storageId.getProviderId());
UserStorageProviderModel model = new UserStorageProviderModel(component);
if (!model.isEnabled()) {
return new ReadOnlyUserModelDelegate(delegate) {
@Override
public boolean isEnabled() {
return false;
}
};
}
UserStorageProviderModel.CachePolicy policy = model.getCachePolicy();
if (policy != null && policy == UserStorageProviderModel.CachePolicy.NO_CACHE) {
return delegate;
Expand Down Expand Up @@ -845,7 +859,7 @@ protected void fullyInvalidateUser(RealmModel realm, UserModel user) {

@Override
public boolean removeUser(RealmModel realm, UserModel user) {
fullyInvalidateUser(realm, user);
fullyInvalidateUser(realm, user);
return getDelegate().removeUser(realm, user);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class UserStorageProviderModel extends PrioritizedComponentModel {
public static final String FULL_SYNC_PERIOD = "fullSyncPeriod";
public static final String CHANGED_SYNC_PERIOD = "changedSyncPeriod";
public static final String LAST_SYNC = "lastSync";
public static final String ENABLED = "enabled";

public static enum CachePolicy {
NO_CACHE,
Expand All @@ -59,6 +60,7 @@ public UserStorageProviderModel(ComponentModel copy) {
private transient Integer changedSyncPeriod;
private transient Integer lastSync;
private transient Boolean importEnabled;
private transient Boolean enabled;
private transient CachePolicy cachePolicy;
private transient long maxLifespan = -1;
private transient int evictionHour = -1;
Expand Down Expand Up @@ -171,13 +173,30 @@ public boolean isImportEnabled() {

}



public void setImportEnabled(boolean flag) {
importEnabled = flag;
getConfig().putSingle(IMPORT_ENABLED, Boolean.toString(flag));
}

public void setEnabled(boolean flag) {
enabled = flag;
getConfig().putSingle(ENABLED, Boolean.toString(flag));
}


public boolean isEnabled() {
if (enabled == null) {
String val = getConfig().getFirst(ENABLED);
if (val == null) {
enabled = true;
} else {
enabled = Boolean.valueOf(val);
}
}
return enabled;

}

public int getFullSyncPeriod() {
if (fullSyncPeriod == null) {
String val = getConfig().getFirst(FULL_SYNC_PERIOD);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ public Class<? extends ProviderFactory> getProviderFactoryClass() {

static {
List<ProviderConfigProperty> config = ProviderConfigurationBuilder.create()
.property()
.name("enabled").type(ProviderConfigProperty.BOOLEAN_TYPE).add()
.property()
.name("priority").type(ProviderConfigProperty.STRING_TYPE).add()
.property()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.keycloak.storage.UserStorageProvider;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
Expand All @@ -49,9 +50,9 @@ public UserCredentialStoreManager(KeycloakSession session) {

protected UserCredentialStore getStoreForUser(UserModel user) {
if (StorageId.isLocalStorage(user)) {
return (UserCredentialStore)session.userLocalStorage();
return (UserCredentialStore) session.userLocalStorage();
} else {
return (UserCredentialStore)session.userFederatedStorage();
return (UserCredentialStore) session.userFederatedStorage();
}
}

Expand Down Expand Up @@ -105,10 +106,11 @@ public boolean isValid(RealmModel realm, UserModel user, List<CredentialInput> i
String providerId = StorageId.resolveProviderId(user);
UserStorageProvider provider = UserStorageManager.getStorageProvider(session, realm, providerId);
if (provider instanceof CredentialInputValidator) {
if (!UserStorageManager.isStorageProviderEnabled(realm, providerId)) return false;
Iterator<CredentialInput> it = toValidate.iterator();
while (it.hasNext()) {
CredentialInput input = it.next();
CredentialInputValidator validator = (CredentialInputValidator)provider;
CredentialInputValidator validator = (CredentialInputValidator) provider;
if (validator.supportsCredentialType(input.getType()) && validator.isValid(realm, user, input)) {
it.remove();
}
Expand All @@ -118,6 +120,7 @@ public boolean isValid(RealmModel realm, UserModel user, List<CredentialInput> i
if (user.getFederationLink() != null) {
UserStorageProvider provider = UserStorageManager.getStorageProvider(session, realm, user.getFederationLink());
if (provider != null && provider instanceof CredentialInputValidator) {
if (!UserStorageManager.isStorageProviderEnabled(realm, user.getFederationLink())) return false;
validate(realm, user, toValidate, ((CredentialInputValidator)provider));
}
}
Expand Down Expand Up @@ -147,7 +150,7 @@ public static <T> List<T> getCredentialProviders(KeycloakSession session, RealmM
List<T> list = new LinkedList<T>();
for (ProviderFactory f : session.getKeycloakSessionFactory().getProviderFactories(CredentialProvider.class)) {
if (!Types.supports(type, f, CredentialProviderFactory.class)) continue;
list.add((T)session.getProvider(CredentialProvider.class, f.getId()));
list.add((T) session.getProvider(CredentialProvider.class, f.getId()));
}
return list;

Expand All @@ -159,16 +162,19 @@ public void updateCredential(RealmModel realm, UserModel user, CredentialInput i
String providerId = StorageId.resolveProviderId(user);
UserStorageProvider provider = UserStorageManager.getStorageProvider(session, realm, providerId);
if (provider instanceof CredentialInputUpdater) {
CredentialInputUpdater updater = (CredentialInputUpdater)provider;
if (!UserStorageManager.isStorageProviderEnabled(realm, providerId)) return;
CredentialInputUpdater updater = (CredentialInputUpdater) provider;
if (updater.supportsCredentialType(input.getType())) {
if (updater.updateCredential(realm, user, input)) return;
}

}
} else {
if (user.getFederationLink() != null) {
UserStorageProvider provider = UserStorageManager.getStorageProvider(session, realm, user.getFederationLink());
if (provider != null && provider instanceof CredentialInputUpdater) {
if (((CredentialInputUpdater)provider).updateCredential(realm, user, input)) return;
if (!UserStorageManager.isStorageProviderEnabled(realm, user.getFederationLink())) return;
if (((CredentialInputUpdater) provider).updateCredential(realm, user, input)) return;
}
}
}
Expand All @@ -180,22 +186,26 @@ public void updateCredential(RealmModel realm, UserModel user, CredentialInput i

}
}

@Override
public void disableCredentialType(RealmModel realm, UserModel user, String credentialType) {
if (!StorageId.isLocalStorage(user)) {
String providerId = StorageId.resolveProviderId(user);
UserStorageProvider provider = UserStorageManager.getStorageProvider(session, realm, providerId);
if (provider instanceof CredentialInputUpdater) {
CredentialInputUpdater updater = (CredentialInputUpdater)provider;
if (!UserStorageManager.isStorageProviderEnabled(realm, providerId)) return;
CredentialInputUpdater updater = (CredentialInputUpdater) provider;
if (updater.supportsCredentialType(credentialType)) {
updater.disableCredentialType(realm, user, credentialType);
}

}
} else {
if (user.getFederationLink() != null) {
UserStorageProvider provider = UserStorageManager.getStorageProvider(session, realm, user.getFederationLink());
if (provider != null && provider instanceof CredentialInputUpdater) {
((CredentialInputUpdater)provider).disableCredentialType(realm, user, credentialType);
if (!UserStorageManager.isStorageProviderEnabled(realm, user.getFederationLink())) return;
((CredentialInputUpdater) provider).disableCredentialType(realm, user, credentialType);
}
}

Expand All @@ -218,14 +228,16 @@ public Set<String> getDisableableCredentialTypes(RealmModel realm, UserModel use
String providerId = StorageId.resolveProviderId(user);
UserStorageProvider provider = UserStorageManager.getStorageProvider(session, realm, providerId);
if (provider instanceof CredentialInputUpdater) {
CredentialInputUpdater updater = (CredentialInputUpdater)provider;
if (!UserStorageManager.isStorageProviderEnabled(realm, providerId)) return Collections.EMPTY_SET;
CredentialInputUpdater updater = (CredentialInputUpdater) provider;
types.addAll(updater.getDisableableCredentialTypes(realm, user));
}
} else {
if (user.getFederationLink() != null) {
UserStorageProvider provider = UserStorageManager.getStorageProvider(session, realm, user.getFederationLink());
if (provider != null && provider instanceof CredentialInputUpdater) {
types.addAll(((CredentialInputUpdater)provider).getDisableableCredentialTypes(realm, user));
if (!UserStorageManager.isStorageProviderEnabled(realm, user.getFederationLink())) return Collections.EMPTY_SET;
types.addAll(((CredentialInputUpdater) provider).getDisableableCredentialTypes(realm, user));
}
}

Expand All @@ -244,7 +256,8 @@ public boolean isConfiguredFor(RealmModel realm, UserModel user, String type) {
String providerId = StorageId.resolveProviderId(user);
UserStorageProvider provider = UserStorageManager.getStorageProvider(session, realm, providerId);
if (provider instanceof CredentialInputValidator) {
CredentialInputValidator validator = (CredentialInputValidator)provider;
if (!UserStorageManager.isStorageProviderEnabled(realm, providerId)) return false;
CredentialInputValidator validator = (CredentialInputValidator) provider;
if (validator.supportsCredentialType(type) && validator.isConfiguredFor(realm, user, type)) {
return true;
}
Expand All @@ -253,7 +266,8 @@ public boolean isConfiguredFor(RealmModel realm, UserModel user, String type) {
if (user.getFederationLink() != null) {
UserStorageProvider provider = UserStorageManager.getStorageProvider(session, realm, user.getFederationLink());
if (provider != null && provider instanceof CredentialInputValidator) {
if (((CredentialInputValidator)provider).isConfiguredFor(realm, user, type)) return true;
if (!UserStorageManager.isStorageProviderEnabled(realm, user.getFederationLink())) return false;
if (((CredentialInputValidator) provider).isConfiguredFor(realm, user, type)) return true;
}
}

Expand All @@ -276,7 +290,7 @@ public boolean isConfiguredLocally(RealmModel realm, UserModel user, String type

@Override
public CredentialValidationOutput authenticate(KeycloakSession session, RealmModel realm, CredentialInput input) {
List<CredentialAuthentication> list = UserStorageManager.getStorageProviders(session, realm, CredentialAuthentication.class);
List<CredentialAuthentication> list = UserStorageManager.getEnabledStorageProviders(session, realm, CredentialAuthentication.class);
for (CredentialAuthentication auth : list) {
if (auth.supportsCredentialAuthenticationFor(input.getType())) {
CredentialValidationOutput output = auth.authenticate(realm, input);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ private class Holder {

public SynchronizationResult syncAllUsers(final KeycloakSessionFactory sessionFactory, final String realmId, final UserStorageProviderModel provider) {
UserStorageProviderFactory factory = (UserStorageProviderFactory) sessionFactory.getProviderFactory(UserStorageProvider.class, provider.getProviderId());
if (!(factory instanceof ImportSynchronization) || !provider.isImportEnabled()) {
if (!(factory instanceof ImportSynchronization) || !provider.isImportEnabled() || !provider.isEnabled()) {
return SynchronizationResult.ignored();

}
Expand Down Expand Up @@ -122,7 +122,7 @@ public SynchronizationResult call() throws Exception {

public SynchronizationResult syncChangedUsers(final KeycloakSessionFactory sessionFactory, final String realmId, final UserStorageProviderModel provider) {
UserStorageProviderFactory factory = (UserStorageProviderFactory) sessionFactory.getProviderFactory(UserStorageProvider.class, provider.getProviderId());
if (!(factory instanceof ImportSynchronization) || !provider.isImportEnabled()) {
if (!(factory instanceof ImportSynchronization) || !provider.isImportEnabled() || !provider.isEnabled()) {
return SynchronizationResult.ignored();

}
Expand Down
Loading

0 comments on commit 5d5a200

Please sign in to comment.