KEYCLOAK-15450 Complement methods for accessing realms with Stream variants

This commit is contained in:
Martin Kanis 2020-09-16 10:04:49 +02:00 committed by Hynek Mlnařík
parent 0621e4ceb9
commit 086f7b4696
148 changed files with 1844 additions and 2294 deletions

View file

@ -25,10 +25,8 @@ import org.keycloak.models.RealmModel;
import org.keycloak.storage.ldap.idm.store.ldap.LDAPIdentityStore;
import org.keycloak.storage.ldap.mappers.LDAPConfigDecorator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@ -68,12 +66,9 @@ public class LDAPIdentityStoreRegistry {
if (logger.isDebugEnabled()) {
RealmModel realm = session.realms().getRealm(ldapModel.getParentId());
List<ComponentModel> mappers = realm.getComponents(ldapModel.getId());
mappers.stream().forEach((ComponentModel c) -> {
logger.debugf("Mapper for provider: %s, Mapper name: %s, Provider: %s, Mapper configuration: %s", ldapModel.getName(), c.getName(), c.getProviderId(), c.getConfig().toString());
});
realm.getComponentsStream(ldapModel.getId()).forEach(c ->
logger.debugf("Mapper for provider: %s, Mapper name: %s, Provider: %s, Mapper configuration: %s",
ldapModel.getName(), c.getName(), c.getProviderId(), c.getConfig().toString()));
}
}

View file

@ -25,6 +25,8 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import javax.naming.AuthenticationException;
@ -37,7 +39,18 @@ import org.keycloak.credential.CredentialInputUpdater;
import org.keycloak.credential.CredentialInputValidator;
import org.keycloak.federation.kerberos.impl.KerberosUsernamePasswordAuthenticator;
import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator;
import org.keycloak.models.*;
import org.keycloak.models.CredentialValidationOutput;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.ModelException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredActionProviderModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserManager;
import org.keycloak.models.UserModel;
import org.keycloak.models.cache.CachedUserModel;
import org.keycloak.models.credential.PasswordCredentialModel;
import org.keycloak.models.utils.DefaultRoles;
@ -58,10 +71,11 @@ import org.keycloak.storage.ldap.idm.query.internal.LDAPQuery;
import org.keycloak.storage.ldap.idm.query.internal.LDAPQueryConditionsBuilder;
import org.keycloak.storage.ldap.idm.store.ldap.LDAPIdentityStore;
import org.keycloak.storage.ldap.kerberos.LDAPProviderKerberosConfig;
import org.keycloak.storage.ldap.mappers.LDAPMappersComparator;
import org.keycloak.storage.ldap.mappers.LDAPOperationDecorator;
import org.keycloak.storage.ldap.mappers.LDAPStorageMapper;
import org.keycloak.storage.ldap.mappers.LDAPStorageMapperManager;
import org.keycloak.storage.ldap.mappers.PasswordUpdateCallback;
import org.keycloak.storage.ldap.mappers.LDAPOperationDecorator;
import org.keycloak.storage.user.ImportedUserValidation;
import org.keycloak.storage.user.UserLookupProvider;
import org.keycloak.storage.user.UserQueryProvider;
@ -91,6 +105,7 @@ public class LDAPStorageProvider implements UserStorageProvider,
protected PasswordUpdateCallback updater;
protected LDAPStorageMapperManager mapperManager;
protected LDAPStorageUserManager userManager;
private LDAPMappersComparator ldapMappersComparator;
// these exist to make sure that we only hit ldap once per transaction
//protected Map<String, UserModel> noImportSessionCache = new HashMap<>();
@ -112,6 +127,8 @@ public class LDAPStorageProvider implements UserStorageProvider,
if (kerberosConfig.isAllowKerberosAuthentication()) {
supportedCredentialTypes.add(UserCredentialModel.KERBEROS);
}
ldapMappersComparator = new LDAPMappersComparator(getLdapIdentityStore().getConfig());
}
public void setUpdater(PasswordUpdateCallback updater) {
@ -192,12 +209,14 @@ public class LDAPStorageProvider implements UserStorageProvider,
break;
}
List<ComponentModel> mappers = realm.getComponents(model.getId(), LDAPStorageMapper.class.getName());
List<ComponentModel> sortedMappers = mapperManager.sortMappersAsc(mappers);
for (ComponentModel mapperModel : sortedMappers) {
LDAPStorageMapper ldapMapper = mapperManager.getMapper(mapperModel);
proxied = ldapMapper.proxy(ldapObject, proxied, realm);
}
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);
@ -241,7 +260,7 @@ public class LDAPStorageProvider implements UserStorageProvider,
return Collections.emptyList();
}
List<UserModel> searchResults = new LinkedList<UserModel>();
List<UserModel> searchResults = new LinkedList<>();
for (LDAPObject ldapUser : ldapObjects) {
String ldapUsername = LDAPUtils.getUsername(ldapUser, this.ldapIdentityStore.getConfig());
@ -286,11 +305,11 @@ public class LDAPStorageProvider implements UserStorageProvider,
realm.getDefaultGroupsStream().forEach(proxy::joinGroup);
for (RequiredActionProviderModel r : realm.getRequiredActionProviders()) {
if (r.isEnabled() && r.isDefaultAction()) {
proxy.addRequiredAction(r.getAlias());
}
}
realm.getRequiredActionProvidersStream()
.filter(RequiredActionProviderModel::isEnabled)
.filter(RequiredActionProviderModel::isDefaultAction)
.map(RequiredActionProviderModel::getAlias)
.forEachOrdered(proxy::addRequiredAction);
return proxy;
}
@ -397,8 +416,10 @@ public class LDAPStorageProvider implements UserStorageProvider,
@Override
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
List<ComponentModel> mappers = realm.getComponents(model.getId(), LDAPStorageMapper.class.getName());
List<ComponentModel> sortedMappers = mapperManager.sortMappersAsc(mappers);
List<ComponentModel> sortedMappers = realm.getComponentsStream(model.getId(), LDAPStorageMapper.class.getName())
.sorted(ldapMappersComparator.sortAsc())
.collect(Collectors.toList());
for (ComponentModel mapperModel : sortedMappers) {
LDAPStorageMapper ldapMapper = mapperManager.getMapper(mapperModel);
List<UserModel> users = ldapMapper.getGroupMembers(realm, group, firstResult, maxResults);
@ -418,8 +439,9 @@ public class LDAPStorageProvider implements UserStorageProvider,
@Override
public List<UserModel> getRoleMembers(RealmModel realm, RoleModel role, int firstResult, int maxResults) {
List<ComponentModel> mappers = realm.getComponents(model.getId(), LDAPStorageMapper.class.getName());
List<ComponentModel> sortedMappers = mapperManager.sortMappersAsc(mappers);
List<ComponentModel> sortedMappers = realm.getComponentsStream(model.getId(), LDAPStorageMapper.class.getName())
.sorted(ldapMappersComparator.sortAsc())
.collect(Collectors.toList());
for (ComponentModel mapperModel : sortedMappers) {
LDAPStorageMapper ldapMapper = mapperManager.getMapper(mapperModel);
List<UserModel> users = ldapMapper.getRoleMembers(realm, role, firstResult, maxResults);
@ -544,15 +566,16 @@ public class LDAPStorageProvider implements UserStorageProvider,
}
imported.setEnabled(true);
List<ComponentModel> mappers = realm.getComponents(model.getId(), LDAPStorageMapper.class.getName());
List<ComponentModel> sortedMappers = mapperManager.sortMappersDesc(mappers);
for (ComponentModel mapperModel : sortedMappers) {
if (logger.isTraceEnabled()) {
logger.tracef("Using mapper %s during import user from LDAP", mapperModel);
}
LDAPStorageMapper ldapMapper = mapperManager.getMapper(mapperModel);
ldapMapper.onImportUserFromLDAP(ldapUser, imported, realm, true);
}
UserModel finalImported = imported;
realm.getComponentsStream(model.getId(), LDAPStorageMapper.class.getName())
.sorted(ldapMappersComparator.sortDesc())
.forEachOrdered(mapperModel -> {
if (logger.isTraceEnabled()) {
logger.tracef("Using mapper %s during import user from LDAP", mapperModel);
}
LDAPStorageMapper ldapMapper = mapperManager.getMapper(mapperModel);
ldapMapper.onImportUserFromLDAP(ldapUser, finalImported, realm, true);
});
String userDN = ldapUser.getDn().toString();
if (model.isImportEnabled()) imported.setFederationLink(model.getId());
@ -631,17 +654,17 @@ public class LDAPStorageProvider implements UserStorageProvider,
ldapIdentityStore.validatePassword(ldapUser, password);
return true;
} catch (AuthenticationException ae) {
boolean processed = false;
List<ComponentModel> mappers = realm.getComponents(model.getId(), LDAPStorageMapper.class.getName());
List<ComponentModel> sortedMappers = mapperManager.sortMappersDesc(mappers);
for (ComponentModel mapperModel : sortedMappers) {
if (logger.isTraceEnabled()) {
logger.tracef("Using mapper %s during import user from LDAP", mapperModel);
}
LDAPStorageMapper ldapMapper = mapperManager.getMapper(mapperModel);
processed = processed || ldapMapper.onAuthenticationFailure(ldapUser, user, ae, realm);
}
return processed;
AtomicReference<Boolean> processed = new AtomicReference<>(false);
realm.getComponentsStream(model.getId(), LDAPStorageMapper.class.getName())
.sorted(ldapMappersComparator.sortDesc())
.forEachOrdered(mapperModel -> {
if (logger.isTraceEnabled()) {
logger.tracef("Using mapper %s during import user from LDAP", mapperModel);
}
LDAPStorageMapper ldapMapper = mapperManager.getMapper(mapperModel);
processed.set(processed.get() || ldapMapper.onAuthenticationFailure(ldapUser, user, ae, realm));
});
return processed.get();
}
}
}

View file

@ -52,8 +52,8 @@ import org.keycloak.storage.ldap.mappers.FullNameLDAPStorageMapperFactory;
import org.keycloak.storage.ldap.mappers.HardcodedLDAPAttributeMapper;
import org.keycloak.storage.ldap.mappers.HardcodedLDAPAttributeMapperFactory;
import org.keycloak.storage.ldap.mappers.LDAPConfigDecorator;
import org.keycloak.storage.ldap.mappers.LDAPMappersComparator;
import org.keycloak.storage.ldap.mappers.LDAPStorageMapper;
import org.keycloak.storage.ldap.mappers.LDAPStorageMapperFactory;
import org.keycloak.storage.ldap.mappers.UserAttributeLDAPStorageMapper;
import org.keycloak.storage.ldap.mappers.UserAttributeLDAPStorageMapperFactory;
import org.keycloak.storage.ldap.mappers.msad.MSADUserAccountControlStorageMapperFactory;
@ -62,9 +62,10 @@ import org.keycloak.storage.user.SynchronizationResult;
import org.keycloak.utils.CredentialHelper;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@ -241,17 +242,12 @@ public class LDAPStorageProviderFactory implements UserStorageProviderFactory<LD
// Check if it's some performance overhead to create this map in every request. But probably not...
protected Map<ComponentModel, LDAPConfigDecorator> getLDAPConfigDecorators(KeycloakSession session, ComponentModel ldapModel) {
RealmModel realm = session.realms().getRealm(ldapModel.getParentId());
List<ComponentModel> mapperComponents = realm.getComponents(ldapModel.getId(), LDAPStorageMapper.class.getName());
Map<ComponentModel, LDAPConfigDecorator> result = new HashMap<>();
for (ComponentModel mapperModel : mapperComponents) {
LDAPStorageMapperFactory mapperFactory = (LDAPStorageMapperFactory) session.getKeycloakSessionFactory().getProviderFactory(LDAPStorageMapper.class, mapperModel.getProviderId());
if (mapperFactory instanceof LDAPConfigDecorator) {
result.put(mapperModel, (LDAPConfigDecorator) mapperFactory);
}
}
return result;
return realm.getComponentsStream(ldapModel.getId(), LDAPStorageMapper.class.getName())
.filter(mapperModel -> session.getKeycloakSessionFactory()
.getProviderFactory(LDAPStorageMapper.class, mapperModel.getProviderId()) instanceof LDAPConfigDecorator)
.collect(Collectors.toMap(Function.identity(), mapperModel ->
(LDAPConfigDecorator) session.getKeycloakSessionFactory()
.getProviderFactory(LDAPStorageMapper.class, mapperModel.getProviderId())));
}
@ -504,14 +500,15 @@ public class LDAPStorageProviderFactory implements UserStorageProviderFactory<LD
RealmModel realm = session.realms().getRealm(realmId);
session.getContext().setRealm(realm);
session.getProvider(UserStorageProvider.class, model);
List<ComponentModel> mappers = realm.getComponents(model.getId(), LDAPStorageMapper.class.getName());
for (ComponentModel mapperModel : mappers) {
LDAPStorageMapper ldapMapper = session.getProvider(LDAPStorageMapper.class, mapperModel);
SynchronizationResult syncResult = ldapMapper.syncDataFromFederationProviderToKeycloak(realm);
if (syncResult.getAdded() > 0 || syncResult.getUpdated() > 0 || syncResult.getRemoved() > 0 || syncResult.getFailed() > 0) {
logger.infof("Sync of federation mapper '%s' finished. Status: %s", mapperModel.getName(), syncResult.toString());
}
}
realm.getComponentsStream(model.getId(), LDAPStorageMapper.class.getName())
.forEach(mapperModel -> {
SynchronizationResult syncResult = session.getProvider(LDAPStorageMapper.class, mapperModel)
.syncDataFromFederationProviderToKeycloak(realm);
if (syncResult.getAdded() > 0 || syncResult.getUpdated() > 0 || syncResult.getRemoved() > 0
|| syncResult.getFailed() > 0) {
logger.infof("Sync of federation mapper '%s' finished. Status: %s", mapperModel.getName(), syncResult.toString());
}
});
}
});
@ -609,12 +606,14 @@ public class LDAPStorageProviderFactory implements UserStorageProviderFactory<LD
if ((fedModel.getId().equals(currentUser.getFederationLink())) && (ldapUser.getUuid().equals(currentUser.getFirstAttribute(LDAPConstants.LDAP_ID)))) {
// Update keycloak user
List<ComponentModel> federationMappers = currentRealm.getComponents(fedModel.getId(), LDAPStorageMapper.class.getName());
List<ComponentModel> sortedMappers = ldapFedProvider.getMapperManager().sortMappersDesc(federationMappers);
for (ComponentModel mapperModel : sortedMappers) {
LDAPStorageMapper ldapMapper = ldapFedProvider.getMapperManager().getMapper(mapperModel);
ldapMapper.onImportUserFromLDAP(ldapUser, currentUser, currentRealm, false);
}
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);

View file

@ -25,6 +25,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import javax.naming.directory.SearchControls;
@ -43,6 +44,7 @@ import org.keycloak.storage.ldap.idm.query.Condition;
import org.keycloak.storage.ldap.idm.query.internal.LDAPQuery;
import org.keycloak.storage.ldap.idm.query.internal.LDAPQueryConditionsBuilder;
import org.keycloak.storage.ldap.idm.store.ldap.LDAPIdentityStore;
import org.keycloak.storage.ldap.mappers.LDAPMappersComparator;
import org.keycloak.storage.ldap.mappers.LDAPStorageMapper;
import org.keycloak.storage.ldap.mappers.membership.MembershipType;
@ -67,12 +69,13 @@ public class LDAPUtils {
ldapUser.setRdnAttributeName(ldapConfig.getRdnLdapAttribute());
ldapUser.setObjectClasses(ldapConfig.getUserObjectClasses());
List<ComponentModel> federationMappers = realm.getComponents(ldapProvider.getModel().getId(), LDAPStorageMapper.class.getName());
List<ComponentModel> sortedMappers = ldapProvider.getMapperManager().sortMappersAsc(federationMappers);
for (ComponentModel mapperModel : sortedMappers) {
LDAPStorageMapper ldapMapper = ldapProvider.getMapperManager().getMapper(mapperModel);
ldapMapper.onRegisterUserToLDAP(ldapUser, user, realm);
}
LDAPMappersComparator ldapMappersComparator = new LDAPMappersComparator(ldapConfig);
realm.getComponentsStream(ldapProvider.getModel().getId(), LDAPStorageMapper.class.getName())
.sorted(ldapMappersComparator.sortAsc())
.forEachOrdered(mapperModel -> {
LDAPStorageMapper ldapMapper = ldapProvider.getMapperManager().getMapper(mapperModel);
ldapMapper.onRegisterUserToLDAP(ldapUser, user, realm);
});
LDAPUtils.computeAndSetDn(ldapConfig, ldapUser);
ldapStore.add(ldapUser);
@ -92,7 +95,9 @@ public class LDAPUtils {
ldapQuery.addWhereCondition(customFilterCondition);
}
List<ComponentModel> mapperModels = realm.getComponents(ldapProvider.getModel().getId(), LDAPStorageMapper.class.getName());
List<ComponentModel> mapperModels = realm
.getComponentsStream(ldapProvider.getModel().getId(), LDAPStorageMapper.class.getName())
.collect(Collectors.toList());
ldapQuery.addMappers(mapperModels);
return ldapQuery;

View file

@ -26,18 +26,14 @@ import org.keycloak.storage.ldap.idm.model.LDAPObject;
import org.keycloak.storage.ldap.idm.query.Condition;
import org.keycloak.storage.ldap.idm.query.Sort;
import org.keycloak.storage.ldap.idm.store.ldap.LDAPContextManager;
import org.keycloak.storage.ldap.mappers.LDAPMappersComparator;
import org.keycloak.storage.ldap.mappers.LDAPStorageMapper;
import javax.naming.NamingException;
import javax.naming.directory.SearchControls;
import javax.naming.ldap.LdapContext;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
import static java.util.Collections.unmodifiableSet;
@ -162,8 +158,10 @@ public class LDAPQuery implements AutoCloseable {
public List<LDAPObject> getResultList() {
// Apply mappers now
List<ComponentModel> sortedMappers = ldapFedProvider.getMapperManager().sortMappersAsc(mappers);
for (ComponentModel mapperModel : sortedMappers) {
LDAPMappersComparator ldapMappersComparator = new LDAPMappersComparator(ldapFedProvider.getLdapIdentityStore().getConfig());
Collections.sort(mappers, ldapMappersComparator.sortAsc());
for (ComponentModel mapperModel : mappers) {
LDAPStorageMapper fedMapper = ldapFedProvider.getMapperManager().getMapper(mapperModel);
fedMapper.beforeLDAPQuery(this);
}

View file

@ -18,6 +18,7 @@
package org.keycloak.storage.ldap.mappers;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.UserModel;
import org.keycloak.storage.ldap.LDAPConfig;
@ -34,20 +35,18 @@ import java.util.List;
*/
public class LDAPMappersComparator {
public static List<ComponentModel> sortAsc(LDAPConfig ldapConfig, Collection<ComponentModel> mappers) {
Comparator<ComponentModel> comparator = new ImportantFirstComparator(ldapConfig);
private LDAPConfig ldapConfig;
List<ComponentModel> result = new ArrayList<>(mappers);
Collections.sort(result, comparator);
return result;
public LDAPMappersComparator(LDAPConfig ldapConfig) {
this.ldapConfig = ldapConfig;
}
public static List<ComponentModel> sortDesc(LDAPConfig ldapConfig, Collection<ComponentModel> mappers) {
Comparator<ComponentModel> comparator = new ImportantFirstComparator(ldapConfig).reversed();
public Comparator<ComponentModel> sortAsc() {
return new ImportantFirstComparator(ldapConfig);
}
List<ComponentModel> result = new ArrayList<>(mappers);
Collections.sort(result, comparator);
return result;
public Comparator<ComponentModel> sortDesc() {
return new ImportantFirstComparator(ldapConfig).reversed();
}

View file

@ -17,9 +17,6 @@
package org.keycloak.storage.ldap.mappers;
import java.util.Collection;
import java.util.List;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.ModelException;
import org.keycloak.storage.ldap.LDAPStorageProvider;
@ -45,15 +42,4 @@ public class LDAPStorageMapperManager {
return ldapMapper;
}
public List<ComponentModel> sortMappersAsc(Collection<ComponentModel> mappers) {
return LDAPMappersComparator.sortAsc(ldapProvider.getLdapIdentityStore().getConfig(), mappers);
}
public List<ComponentModel> sortMappersDesc(Collection<ComponentModel> mappers) {
return LDAPMappersComparator.sortDesc(ldapProvider.getLdapIdentityStore().getConfig(), mappers);
}
}

View file

@ -32,6 +32,7 @@ import org.keycloak.storage.ldap.mappers.LDAPStorageMapper;
import org.keycloak.storage.ldap.mappers.UserAttributeLDAPStorageMapper;
import org.keycloak.storage.ldap.mappers.UserAttributeLDAPStorageMapperFactory;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@ -46,26 +47,30 @@ public class LDAPMappersComparatorTest {
public void testCompareWithCNUsername() {
MultivaluedHashMap<String, String> cfg = new MultivaluedHashMap<>();
cfg.add(LDAPConstants.USERNAME_LDAP_ATTRIBUTE, LDAPConstants.CN);
LDAPConfig config = new LDAPConfig(cfg);
LDAPMappersComparator ldapMappersComparator = new LDAPMappersComparator(new LDAPConfig(cfg));
List<ComponentModel> sorted = LDAPMappersComparator.sortAsc(config, getMappers());
assertOrder(sorted, "username-cn", "sAMAccountName", "first name", "full name");
List<ComponentModel> mappers = getMappers();
sorted = LDAPMappersComparator.sortDesc(config, getMappers());
assertOrder(sorted, "full name", "first name", "sAMAccountName", "username-cn");
Collections.sort(mappers, ldapMappersComparator.sortAsc());
assertOrder(mappers, "username-cn", "sAMAccountName", "first name", "full name");
Collections.sort(mappers, ldapMappersComparator.sortDesc());
assertOrder(mappers, "full name", "first name", "sAMAccountName", "username-cn");
}
@Test
public void testCompareWithSAMAccountNameUsername() {
MultivaluedHashMap<String, String> cfg = new MultivaluedHashMap<>();
cfg.add(LDAPConstants.USERNAME_LDAP_ATTRIBUTE, LDAPConstants.SAM_ACCOUNT_NAME);
LDAPConfig config = new LDAPConfig(cfg);
LDAPMappersComparator ldapMappersComparator = new LDAPMappersComparator(new LDAPConfig(cfg));
List<ComponentModel> sorted = LDAPMappersComparator.sortAsc(config, getMappers());
assertOrder(sorted, "sAMAccountName", "username-cn", "first name", "full name");
List<ComponentModel> mappers = getMappers();
sorted = LDAPMappersComparator.sortDesc(config, getMappers());
assertOrder(sorted, "full name", "first name", "username-cn", "sAMAccountName");
Collections.sort(mappers, ldapMappersComparator.sortAsc());
assertOrder(mappers, "sAMAccountName", "username-cn", "first name", "full name");
Collections.sort(mappers, ldapMappersComparator.sortDesc());
assertOrder(mappers, "full name", "first name", "username-cn", "sAMAccountName");
}
private void assertOrder(List<ComponentModel> result, String... names) {

View file

@ -638,9 +638,9 @@ public class RealmAdapter implements CachedRealmModel {
}
@Override
public List<RequiredCredentialModel> getRequiredCredentials() {
if (isUpdated()) return updated.getRequiredCredentials();
return cached.getRequiredCredentials();
public Stream<RequiredCredentialModel> getRequiredCredentialsStream() {
if (isUpdated()) return updated.getRequiredCredentialsStream();
return cached.getRequiredCredentials().stream();
}
@Override
@ -833,21 +833,18 @@ public class RealmAdapter implements CachedRealmModel {
@Override
public List<IdentityProviderModel> getIdentityProviders() {
if (isUpdated()) return updated.getIdentityProviders();
return cached.getIdentityProviders();
public Stream<IdentityProviderModel> getIdentityProvidersStream() {
if (isUpdated()) return updated.getIdentityProvidersStream();
return cached.getIdentityProviders().stream();
}
@Override
public IdentityProviderModel getIdentityProviderByAlias(String alias) {
if (isUpdated()) return updated.getIdentityProviderByAlias(alias);
for (IdentityProviderModel identityProviderModel : getIdentityProviders()) {
if (identityProviderModel.getAlias().equals(alias)) {
return identityProviderModel;
}
}
return null;
return getIdentityProvidersStream()
.filter(model -> Objects.equals(model.getAlias(), alias))
.findFirst()
.orElse(null);
}
@Override
@ -953,9 +950,9 @@ public class RealmAdapter implements CachedRealmModel {
}
@Override
public Set<String> getEventsListeners() {
if (isUpdated()) return updated.getEventsListeners();
return cached.getEventsListeners();
public Stream<String> getEventsListenersStream() {
if (isUpdated()) return updated.getEventsListenersStream();
return cached.getEventsListeners().stream();
}
@Override
@ -965,9 +962,9 @@ public class RealmAdapter implements CachedRealmModel {
}
@Override
public Set<String> getEnabledEventTypes() {
if (isUpdated()) return updated.getEnabledEventTypes();
return cached.getEnabledEventTypes();
public Stream<String> getEnabledEventTypesStream() {
if (isUpdated()) return updated.getEnabledEventTypesStream();
return cached.getEnabledEventTypes().stream();
}
@Override
@ -1081,9 +1078,9 @@ public class RealmAdapter implements CachedRealmModel {
}
@Override
public Set<String> getSupportedLocales() {
if (isUpdated()) return updated.getSupportedLocales();
return cached.getSupportedLocales();
public Stream<String> getSupportedLocalesStream() {
if (isUpdated()) return updated.getSupportedLocalesStream();
return cached.getSupportedLocales().stream();
}
@Override
@ -1104,20 +1101,16 @@ public class RealmAdapter implements CachedRealmModel {
}
@Override
public Set<IdentityProviderMapperModel> getIdentityProviderMappers() {
if (isUpdated()) return updated.getIdentityProviderMappers();
return cached.getIdentityProviderMapperSet();
public Stream<IdentityProviderMapperModel> getIdentityProviderMappersStream() {
if (isUpdated()) return updated.getIdentityProviderMappersStream();
return cached.getIdentityProviderMapperSet().stream();
}
@Override
public Set<IdentityProviderMapperModel> getIdentityProviderMappersByAlias(String brokerAlias) {
if (isUpdated()) return updated.getIdentityProviderMappersByAlias(brokerAlias);
Set<IdentityProviderMapperModel> mappings = new HashSet<>();
List<IdentityProviderMapperModel> list = cached.getIdentityProviderMappers().getList(brokerAlias);
for (IdentityProviderMapperModel entity : list) {
mappings.add(entity);
}
return Collections.unmodifiableSet(mappings);
public Stream<IdentityProviderMapperModel> getIdentityProviderMappersByAliasStream(String brokerAlias) {
if (isUpdated()) return updated.getIdentityProviderMappersByAliasStream(brokerAlias);
Set<IdentityProviderMapperModel> mappings = new HashSet<>(cached.getIdentityProviderMappers().getList(brokerAlias));
return mappings.stream();
}
@Override
@ -1236,29 +1229,25 @@ public class RealmAdapter implements CachedRealmModel {
}
@Override
public List<AuthenticationFlowModel> getAuthenticationFlows() {
if (isUpdated()) return updated.getAuthenticationFlows();
return cached.getAuthenticationFlowList();
public Stream<AuthenticationFlowModel> getAuthenticationFlowsStream() {
if (isUpdated()) return updated.getAuthenticationFlowsStream();
return cached.getAuthenticationFlowList().stream();
}
@Override
public AuthenticationFlowModel getFlowByAlias(String alias) {
for (AuthenticationFlowModel flow : getAuthenticationFlows()) {
if (flow.getAlias().equals(alias)) {
return flow;
}
}
return null;
return getAuthenticationFlowsStream()
.filter(flow -> Objects.equals(flow.getAlias(), alias))
.findFirst()
.orElse(null);
}
@Override
public AuthenticatorConfigModel getAuthenticatorConfigByAlias(String alias) {
for (AuthenticatorConfigModel config : getAuthenticatorConfigs()) {
if (config.getAlias().equals(alias)) {
return config;
}
}
return null;
return getAuthenticatorConfigsStream()
.filter(config -> Objects.equals(config.getAlias(), alias))
.findFirst()
.orElse(null);
}
@ -1289,9 +1278,9 @@ public class RealmAdapter implements CachedRealmModel {
}
@Override
public List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId) {
if (isUpdated()) return updated.getAuthenticationExecutions(flowId);
return cached.getAuthenticationExecutions().get(flowId);
public Stream<AuthenticationExecutionModel> getAuthenticationExecutionsStream(String flowId) {
if (isUpdated()) return updated.getAuthenticationExecutionsStream(flowId);
return cached.getAuthenticationExecutions().get(flowId).stream();
}
@Override
@ -1327,11 +1316,9 @@ public class RealmAdapter implements CachedRealmModel {
}
@Override
public List<AuthenticatorConfigModel> getAuthenticatorConfigs() {
if (isUpdated()) return updated.getAuthenticatorConfigs();
List<AuthenticatorConfigModel> models = new ArrayList<>();
models.addAll(cached.getAuthenticatorConfigs().values());
return Collections.unmodifiableList(models);
public Stream<AuthenticatorConfigModel> getAuthenticatorConfigsStream() {
if (isUpdated()) return updated.getAuthenticatorConfigsStream();
return cached.getAuthenticatorConfigs().values().stream();
}
@Override
@ -1361,9 +1348,9 @@ public class RealmAdapter implements CachedRealmModel {
}
@Override
public List<RequiredActionProviderModel> getRequiredActionProviders() {
if (isUpdated()) return updated.getRequiredActionProviders();
return cached.getRequiredActionProviderList();
public Stream<RequiredActionProviderModel> getRequiredActionProvidersStream() {
if (isUpdated()) return updated.getRequiredActionProvidersStream();
return cached.getRequiredActionProviderList().stream();
}
@Override
@ -1449,20 +1436,15 @@ public class RealmAdapter implements CachedRealmModel {
}
@Override
public List<ClientScopeModel> getClientScopes() {
if (isUpdated()) return updated.getClientScopes();
List<String> clientScopes = cached.getClientScopes();
if (clientScopes.isEmpty()) return Collections.EMPTY_LIST;
List<ClientScopeModel> apps = new LinkedList<>();
for (String id : clientScopes) {
ClientScopeModel model = cacheSession.getClientScopeById(id, this);
public Stream<ClientScopeModel> getClientScopesStream() {
if (isUpdated()) return updated.getClientScopesStream();
return cached.getClientScopes().stream().map(scope -> {
ClientScopeModel model = cacheSession.getClientScopeById(scope, this);
if (model == null) {
throw new IllegalStateException("Cached clientScope not found: " + id);
throw new IllegalStateException("Cached clientScope not found: " + scope);
}
apps.add(model);
}
return Collections.unmodifiableList(apps);
return model;
});
}
@Override
@ -1507,19 +1489,12 @@ public class RealmAdapter implements CachedRealmModel {
}
@Override
public List<ClientScopeModel> getDefaultClientScopes(boolean defaultScope) {
if (isUpdated()) return updated.getDefaultClientScopes(defaultScope);
public Stream<ClientScopeModel> getDefaultClientScopesStream(boolean defaultScope) {
if (isUpdated()) return updated.getDefaultClientScopesStream(defaultScope);
List<String> clientScopeIds = defaultScope ? cached.getDefaultDefaultClientScopes() : cached.getOptionalDefaultClientScopes();
List<ClientScopeModel> clientScopes = new LinkedList<>();
for (String scopeId : clientScopeIds) {
ClientScopeModel clientScope = cacheSession.getClientScopeById(scopeId, this);
if (clientScope != null) {
clientScopes.add(clientScope);
}
}
return clientScopes;
return clientScopeIds.stream()
.map(scope -> cacheSession.getClientScopeById(scope, this))
.filter(Objects::nonNull);
}
@Override
@ -1588,27 +1563,21 @@ public class RealmAdapter implements CachedRealmModel {
}
@Override
public List<ComponentModel> getComponents(String parentId, String providerType) {
if (isUpdated()) return updated.getComponents(parentId, providerType);
List<ComponentModel> components = cached.getComponentsByParentAndType().getList(parentId + providerType);
if (components == null) return Collections.EMPTY_LIST;
return Collections.unmodifiableList(components);
public Stream<ComponentModel> getComponentsStream(String parentId, String providerType) {
if (isUpdated()) return updated.getComponentsStream(parentId, providerType);
return cached.getComponentsByParentAndType().getList(parentId + providerType).stream();
}
@Override
public List<ComponentModel> getComponents(String parentId) {
if (isUpdated()) return updated.getComponents(parentId);
List<ComponentModel> components = cached.getComponentsByParent().getList(parentId);
if (components == null) return Collections.EMPTY_LIST;
return Collections.unmodifiableList(components);
public Stream<ComponentModel> getComponentsStream(String parentId) {
if (isUpdated()) return updated.getComponentsStream(parentId);
return cached.getComponentsByParent().getList(parentId).stream();
}
@Override
public List<ComponentModel> getComponents() {
if (isUpdated()) return updated.getComponents();
List<ComponentModel> results = new LinkedList<>();
results.addAll(cached.getComponents().values());
return Collections.unmodifiableList(results);
public Stream<ComponentModel> getComponentsStream() {
if (isUpdated()) return updated.getComponentsStream();
return cached.getComponents().values().stream();
}
@Override

View file

@ -468,27 +468,20 @@ public class RealmCacheSession implements CacheRealmProvider {
}
@Override
public List<RealmModel> getRealmsWithProviderType(Class<?> type) {
public Stream<RealmModel> getRealmsWithProviderTypeStream(Class<?> type) {
// Retrieve realms from backend
List<RealmModel> backendRealms = getRealmDelegate().getRealmsWithProviderType(type);
return getRealms(backendRealms);
return getRealms(getRealmDelegate().getRealmsWithProviderTypeStream(type));
}
@Override
public List<RealmModel> getRealms() {
public Stream<RealmModel> getRealmsStream() {
// Retrieve realms from backend
List<RealmModel> backendRealms = getRealmDelegate().getRealms();
return getRealms(backendRealms);
return getRealms(getRealmDelegate().getRealmsStream());
}
private List<RealmModel> getRealms(List<RealmModel> backendRealms) {
private Stream<RealmModel> getRealms(Stream<RealmModel> backendRealms) {
// Return cache delegates to ensure cache invalidated during write operations
List<RealmModel> cachedRealms = new LinkedList<>();
for (RealmModel realm : backendRealms) {
RealmModel cached = getRealm(realm.getId());
cachedRealms.add(cached);
}
return cachedRealms;
return backendRealms.map(RealmModel::getId).map(this::getRealm);
}
@Override
@ -1240,8 +1233,8 @@ public class RealmCacheSession implements CacheRealmProvider {
}
@Override
public List<ClientInitialAccessModel> listClientInitialAccess(RealmModel realm) {
return getRealmDelegate().listClientInitialAccess(realm);
public Stream<ClientInitialAccessModel> listClientInitialAccessStream(RealmModel realm) {
return getRealmDelegate().listClientInitialAccessStream(realm);
}
@Override

View file

@ -35,7 +35,6 @@ import org.keycloak.models.RequiredActionProviderModel;
import org.keycloak.models.RequiredCredentialModel;
import org.keycloak.models.WebAuthnPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@ -43,6 +42,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
@ -113,14 +113,14 @@ public class CachedRealm extends AbstractExtendableRevisioned {
protected List<RequiredCredentialModel> requiredCredentials;
protected MultivaluedHashMap<String, ComponentModel> componentsByParent = new MultivaluedHashMap<>();
protected MultivaluedHashMap<String, ComponentModel> componentsByParentAndType = new MultivaluedHashMap<>();
protected Map<String, ComponentModel> components = new HashMap<>();
protected Map<String, ComponentModel> components;
protected List<IdentityProviderModel> identityProviders;
protected Map<String, String> browserSecurityHeaders;
protected Map<String, String> smtpConfig;
protected Map<String, AuthenticationFlowModel> authenticationFlows = new HashMap<>();
protected List<AuthenticationFlowModel> authenticationFlowList;
protected Map<String, AuthenticatorConfigModel> authenticatorConfigs = new HashMap<>();
protected Map<String, AuthenticatorConfigModel> authenticatorConfigs;
protected Map<String, RequiredActionProviderModel> requiredActionProviders = new HashMap<>();
protected List<RequiredActionProviderModel> requiredActionProviderList;
protected Map<String, RequiredActionProviderModel> requiredActionProvidersByAlias = new HashMap<>();
@ -224,17 +224,14 @@ public class CachedRealm extends AbstractExtendableRevisioned {
adminTheme = model.getAdminTheme();
emailTheme = model.getEmailTheme();
requiredCredentials = model.getRequiredCredentials();
requiredCredentials = model.getRequiredCredentialsStream().collect(Collectors.toList());
userActionTokenLifespans = Collections.unmodifiableMap(new HashMap<>(model.getUserActionTokenLifespans()));
this.identityProviders = new ArrayList<>();
for (IdentityProviderModel identityProviderModel : model.getIdentityProviders()) {
this.identityProviders.add(new IdentityProviderModel(identityProviderModel));
}
this.identityProviders = model.getIdentityProvidersStream().map(IdentityProviderModel::new)
.collect(Collectors.toList());
this.identityProviders = Collections.unmodifiableList(this.identityProviders);
this.identityProviderMapperSet = model.getIdentityProviderMappers();
this.identityProviderMapperSet = model.getIdentityProviderMappersStream().collect(Collectors.toSet());
for (IdentityProviderMapperModel mapper : identityProviderMapperSet) {
identityProviderMappers.add(mapper.getIdentityProviderAlias(), mapper);
}
@ -246,8 +243,8 @@ public class CachedRealm extends AbstractExtendableRevisioned {
eventsEnabled = model.isEventsEnabled();
eventsExpiration = model.getEventsExpiration();
eventsListeners = model.getEventsListeners();
enabledEventTypes = model.getEnabledEventTypes();
eventsListeners = model.getEventsListenersStream().collect(Collectors.toSet());
enabledEventTypes = model.getEnabledEventTypesStream().collect(Collectors.toSet());
adminEventsEnabled = model.isAdminEventsEnabled();
adminEventsDetailsEnabled = model.isAdminEventsDetailsEnabled();
@ -259,25 +256,24 @@ public class CachedRealm extends AbstractExtendableRevisioned {
cacheClientScopes(model);
internationalizationEnabled = model.isInternationalizationEnabled();
supportedLocales = model.getSupportedLocales();
supportedLocales = model.getSupportedLocalesStream().collect(Collectors.toSet());
defaultLocale = model.getDefaultLocale();
authenticationFlowList = model.getAuthenticationFlows();
authenticationFlowList = model.getAuthenticationFlowsStream().collect(Collectors.toList());
for (AuthenticationFlowModel flow : authenticationFlowList) {
this.authenticationFlows.put(flow.getId(), flow);
authenticationExecutions.put(flow.getId(), new LinkedList<>());
for (AuthenticationExecutionModel execution : model.getAuthenticationExecutions(flow.getId())) {
model.getAuthenticationExecutionsStream(flow.getId()).forEachOrdered(execution -> {
authenticationExecutions.add(flow.getId(), execution);
executionsById.put(execution.getId(), execution);
if (execution.getFlowId() != null) {
executionsByFlowId.put(execution.getFlowId(), execution);
}
}
});
}
for (AuthenticatorConfigModel authenticator : model.getAuthenticatorConfigs()) {
authenticatorConfigs.put(authenticator.getId(), authenticator);
}
requiredActionProviderList = model.getRequiredActionProviders();
authenticatorConfigs = model.getAuthenticatorConfigsStream()
.collect(Collectors.toMap(AuthenticatorConfigModel::getId, Function.identity()));
requiredActionProviderList = model.getRequiredActionProvidersStream().collect(Collectors.toList());
for (RequiredActionProviderModel action : requiredActionProviderList) {
this.requiredActionProviders.put(action.getId(), action);
requiredActionProvidersByAlias.put(action.getAlias(), action);
@ -292,15 +288,13 @@ public class CachedRealm extends AbstractExtendableRevisioned {
clientAuthenticationFlow = model.getClientAuthenticationFlow();
dockerAuthenticationFlow = model.getDockerAuthenticationFlow();
for (ComponentModel component : model.getComponents()) {
componentsByParentAndType.add(component.getParentId() + component.getProviderType(), component);
}
for (ComponentModel component : model.getComponents()) {
componentsByParent.add(component.getParentId(), component);
}
for (ComponentModel component : model.getComponents()) {
components.put(component.getId(), component);
}
model.getComponentsStream().forEach(component ->
componentsByParentAndType.add(component.getParentId() + component.getProviderType(), component)
);
model.getComponentsStream().forEach(component ->
componentsByParent.add(component.getParentId(), component)
);
components = model.getComponentsStream().collect(Collectors.toMap(component -> component.getId(), Function.identity()));
try {
attributes = model.getAttributes();
@ -310,15 +304,11 @@ public class CachedRealm extends AbstractExtendableRevisioned {
}
protected void cacheClientScopes(RealmModel model) {
for (ClientScopeModel clientScope : model.getClientScopes()) {
clientScopes.add(clientScope.getId());
}
for (ClientScopeModel clientScope : model.getDefaultClientScopes(true)) {
defaultDefaultClientScopes.add(clientScope.getId());
}
for (ClientScopeModel clientScope : model.getDefaultClientScopes(false)) {
optionalDefaultClientScopes.add(clientScope.getId());
}
clientScopes = model.getClientScopesStream().map(ClientScopeModel::getId).collect(Collectors.toList());
defaultDefaultClientScopes = model.getDefaultClientScopesStream(true).map(ClientScopeModel::getId)
.collect(Collectors.toList());
optionalDefaultClientScopes = model.getDefaultClientScopesStream(false).map(ClientScopeModel::getId)
.collect(Collectors.toList());
}
public String getMasterAdminClient() {

View file

@ -33,6 +33,9 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Stream;
import static org.keycloak.utils.StreamsUtil.closing;
/**
* @author <a href="mailto:giriraj.sharma27@gmail.com">Giriraj Sharma</a>
@ -140,7 +143,7 @@ public class JpaAdminEventQuery implements AdminEventQuery {
}
@Override
public List<AdminEvent> getResultList() {
public Stream<AdminEvent> getResultStream() {
if (!predicates.isEmpty()) {
cq.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
}
@ -157,12 +160,7 @@ public class JpaAdminEventQuery implements AdminEventQuery {
query.setMaxResults(maxResults);
}
List<AdminEvent> events = new LinkedList<AdminEvent>();
for (AdminEventEntity e : query.getResultList()) {
events.add(JpaEventStoreProvider.convertAdminEvent(e));
}
return events;
return closing(query.getResultStream().map(JpaEventStoreProvider::convertAdminEvent));
}
}

View file

@ -31,6 +31,9 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Stream;
import static org.keycloak.utils.StreamsUtil.closing;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -113,7 +116,7 @@ public class JpaEventQuery implements EventQuery {
}
@Override
public List<Event> getResultList() {
public Stream<Event> getResultStream() {
if (!predicates.isEmpty()) {
cq.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
}
@ -130,12 +133,8 @@ public class JpaEventQuery implements EventQuery {
query.setMaxResults(maxResults);
}
List<Event> events = new LinkedList<Event>();
for (EventEntity e : query.getResultList()) {
events.add(JpaEventStoreProvider.convertEvent(e));
}
return events;
return closing(query.getResultStream().map(JpaEventStoreProvider::convertEvent));
}
}

View file

@ -110,26 +110,20 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider, GroupPro
}
@Override
public List<RealmModel> getRealmsWithProviderType(Class<?> providerType) {
public Stream<RealmModel> getRealmsWithProviderTypeStream(Class<?> providerType) {
TypedQuery<String> query = em.createNamedQuery("getRealmIdsWithProviderType", String.class);
query.setParameter("providerType", providerType.getName());
return getRealms(query);
}
@Override
public List<RealmModel> getRealms() {
public Stream<RealmModel> getRealmsStream() {
TypedQuery<String> query = em.createNamedQuery("getAllRealmIds", String.class);
return getRealms(query);
}
private List<RealmModel> getRealms(TypedQuery<String> query) {
List<String> entities = query.getResultList();
List<RealmModel> realms = new ArrayList<RealmModel>();
for (String id : entities) {
RealmModel realm = session.realms().getRealm(id);
if (realm != null) realms.add(realm);
}
return realms;
private Stream<RealmModel> getRealms(TypedQuery<String> query) {
return closing(query.getResultStream().map(session.realms()::getRealm).filter(Objects::nonNull));
}
@Override
@ -843,16 +837,12 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider, GroupPro
}
@Override
public List<ClientInitialAccessModel> listClientInitialAccess(RealmModel realm) {
public Stream<ClientInitialAccessModel> listClientInitialAccessStream(RealmModel realm) {
RealmEntity realmEntity = em.find(RealmEntity.class, realm.getId());
TypedQuery<ClientInitialAccessEntity> query = em.createNamedQuery("findClientInitialAccessByRealm", ClientInitialAccessEntity.class);
query.setParameter("realm", realmEntity);
List<ClientInitialAccessEntity> entities = query.getResultList();
return entities.stream()
.map(this::entityToModel)
.collect(Collectors.toList());
return closing(query.getResultStream().map(this::entityToModel));
}
@Override

View file

@ -57,15 +57,7 @@ import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.Subquery;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;
import javax.persistence.LockModeType;
@ -114,12 +106,14 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
realm.getDefaultGroupsStream().forEach(userModel::joinGroupImpl);
}
if (addDefaultRequiredActions){
for (RequiredActionProviderModel r : realm.getRequiredActionProviders()) {
if (r.isEnabled() && r.isDefaultAction()) {
userModel.addRequiredAction(r.getAlias());
}
}
if (addDefaultRequiredActions) {
Optional<String> requiredAction = realm.getRequiredActionProvidersStream()
.filter(RequiredActionProviderModel::isEnabled)
.filter(RequiredActionProviderModel::isDefaultAction)
.map(RequiredActionProviderModel::getAlias)
.findFirst();
if (requiredAction.isPresent())
userModel.addRequiredAction(requiredAction.get());
}
return userModel;

View file

@ -33,10 +33,10 @@ import javax.persistence.LockModeType;
import javax.persistence.TypedQuery;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.util.Objects.nonNull;
import static org.keycloak.utils.StreamsUtil.closing;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -701,19 +701,8 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
@Override
public List<RequiredCredentialModel> getRequiredCredentials() {
Collection<RequiredCredentialEntity> entities = realm.getRequiredCredentials();
if (entities == null) return Collections.EMPTY_LIST;
List<RequiredCredentialModel> requiredCredentialModels = new LinkedList<>();
for (RequiredCredentialEntity entity : entities) {
RequiredCredentialModel model = new RequiredCredentialModel();
model.setFormLabel(entity.getFormLabel());
model.setType(entity.getType());
model.setSecret(entity.isSecret());
model.setInput(entity.isInput());
requiredCredentialModels.add(model);
}
return Collections.unmodifiableList(requiredCredentialModels);
public Stream<RequiredCredentialModel> getRequiredCredentialsStream() {
return realm.getRequiredCredentials().stream().map(this::toRequiredCredentialModel);
}
@ -1179,12 +1168,8 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
}
@Override
public Set<String> getEventsListeners() {
Set<String> eventsListeners = realm.getEventsListeners();
if (eventsListeners.isEmpty()) return Collections.EMPTY_SET;
Set<String> copy = new HashSet<>();
copy.addAll(eventsListeners);
return Collections.unmodifiableSet(copy);
public Stream<String> getEventsListenersStream() {
return realm.getEventsListeners().stream();
}
@Override
@ -1194,12 +1179,8 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
}
@Override
public Set<String> getEnabledEventTypes() {
Set<String> enabledEventTypes = realm.getEnabledEventTypes();
if (enabledEventTypes.isEmpty()) return Collections.EMPTY_SET;
Set<String> copy = new HashSet<>();
copy.addAll(enabledEventTypes);
return Collections.unmodifiableSet(copy);
public Stream<String> getEnabledEventTypesStream() {
return realm.getEnabledEventTypes().stream();
}
@Override
@ -1250,18 +1231,8 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
}
@Override
public List<IdentityProviderModel> getIdentityProviders() {
List<IdentityProviderEntity> entities = realm.getIdentityProviders();
if (entities.isEmpty()) return Collections.EMPTY_LIST;
List<IdentityProviderModel> identityProviders = new ArrayList<IdentityProviderModel>();
for (IdentityProviderEntity entity: entities) {
IdentityProviderModel identityProviderModel = entityToModel(entity);
identityProviders.add(identityProviderModel);
}
return Collections.unmodifiableList(identityProviders);
public Stream<IdentityProviderModel> getIdentityProvidersStream() {
return realm.getIdentityProviders().stream().map(this::entityToModel);
}
private IdentityProviderModel entityToModel(IdentityProviderEntity entity) {
@ -1288,13 +1259,10 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
@Override
public IdentityProviderModel getIdentityProviderByAlias(String alias) {
for (IdentityProviderModel identityProviderModel : getIdentityProviders()) {
if (identityProviderModel.getAlias().equals(alias)) {
return identityProviderModel;
}
}
return null;
return getIdentityProvidersStream()
.filter(model -> Objects.equals(model.getAlias(), alias))
.findFirst()
.orElse(null);
}
@Override
@ -1414,12 +1382,8 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
}
@Override
public Set<String> getSupportedLocales() {
Set<String> supportedLocales = realm.getSupportedLocales();
if (supportedLocales == null || supportedLocales.isEmpty()) return Collections.EMPTY_SET;
Set<String> copy = new HashSet<>();
copy.addAll(supportedLocales);
return Collections.unmodifiableSet(copy);
public Stream<String> getSupportedLocalesStream() {
return realm.getSupportedLocales().stream();
}
@Override
@ -1440,28 +1404,15 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
}
@Override
public Set<IdentityProviderMapperModel> getIdentityProviderMappers() {
Collection<IdentityProviderMapperEntity> entities = this.realm.getIdentityProviderMappers();
if (entities.isEmpty()) return Collections.EMPTY_SET;
Set<IdentityProviderMapperModel> mappings = new HashSet<IdentityProviderMapperModel>();
for (IdentityProviderMapperEntity entity : entities) {
IdentityProviderMapperModel mapping = entityToModel(entity);
mappings.add(mapping);
}
return Collections.unmodifiableSet(mappings);
public Stream<IdentityProviderMapperModel> getIdentityProviderMappersStream() {
return realm.getIdentityProviderMappers().stream().map(this::entityToModel);
}
@Override
public Set<IdentityProviderMapperModel> getIdentityProviderMappersByAlias(String brokerAlias) {
Set<IdentityProviderMapperModel> mappings = new HashSet<IdentityProviderMapperModel>();
for (IdentityProviderMapperEntity entity : this.realm.getIdentityProviderMappers()) {
if (!entity.getIdentityProviderAlias().equals(brokerAlias)) {
continue;
}
IdentityProviderMapperModel mapping = entityToModel(entity);
mappings.add(mapping);
}
return mappings;
public Stream<IdentityProviderMapperModel> getIdentityProviderMappersByAliasStream(String brokerAlias) {
return realm.getIdentityProviderMappers().stream()
.filter(e -> Objects.equals(e.getIdentityProviderAlias(), brokerAlias))
.map(this::entityToModel);
}
@Override
@ -1630,31 +1581,24 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
}
@Override
public List<AuthenticationFlowModel> getAuthenticationFlows() {
return realm.getAuthenticationFlows().stream()
.map(this::entityToModel)
.collect(Collectors.collectingAndThen(
Collectors.toList(), Collections::unmodifiableList));
public Stream<AuthenticationFlowModel> getAuthenticationFlowsStream() {
return realm.getAuthenticationFlows().stream().map(this::entityToModel);
}
@Override
public AuthenticationFlowModel getFlowByAlias(String alias) {
for (AuthenticationFlowModel flow : getAuthenticationFlows()) {
if (flow.getAlias().equals(alias)) {
return flow;
}
}
return null;
return getAuthenticationFlowsStream()
.filter(flow -> Objects.equals(flow.getAlias(), alias))
.findFirst()
.orElse(null);
}
@Override
public AuthenticatorConfigModel getAuthenticatorConfigByAlias(String alias) {
for (AuthenticatorConfigModel config : getAuthenticatorConfigs()) {
if (config.getAlias().equals(alias)) {
return config;
}
}
return null;
return getAuthenticatorConfigsStream()
.filter(config -> Objects.equals(config.getAlias(), alias))
.findFirst()
.orElse(null);
}
protected AuthenticationFlowModel entityToModel(AuthenticationFlowEntity entity) {
@ -1725,15 +1669,13 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
}
@Override
public List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId) {
public Stream<AuthenticationExecutionModel> getAuthenticationExecutionsStream(String flowId) {
AuthenticationFlowEntity flow = em.getReference(AuthenticationFlowEntity.class, flowId);
return flow.getExecutions().stream()
.filter(e -> getId().equals(e.getRealm().getId()))
.map(this::entityToModel)
.sorted(AuthenticationExecutionModel.ExecutionComparator.SINGLETON)
.collect(Collectors.collectingAndThen(
Collectors.toList(), Collections::unmodifiableList));
.sorted(AuthenticationExecutionModel.ExecutionComparator.SINGLETON);
}
public AuthenticationExecutionModel entityToModel(AuthenticationExecutionEntity entity) {
@ -1889,14 +1831,8 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
}
@Override
public List<AuthenticatorConfigModel> getAuthenticatorConfigs() {
Collection<AuthenticatorConfigEntity> entities = realm.getAuthenticatorConfigs();
if (entities.isEmpty()) return Collections.EMPTY_LIST;
List<AuthenticatorConfigModel> authenticators = new LinkedList<>();
for (AuthenticatorConfigEntity entity : entities) {
authenticators.add(entityToModel(entity));
}
return Collections.unmodifiableList(authenticators);
public Stream<AuthenticatorConfigModel> getAuthenticatorConfigsStream() {
return realm.getAuthenticatorConfigs().stream().map(this::entityToModel);
}
@Override
@ -1973,15 +1909,10 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
}
@Override
public List<RequiredActionProviderModel> getRequiredActionProviders() {
Collection<RequiredActionProviderEntity> entities = realm.getRequiredActionProviders();
if (entities.isEmpty()) return Collections.EMPTY_LIST;
List<RequiredActionProviderModel> actions = new LinkedList<>();
for (RequiredActionProviderEntity entity : entities) {
actions.add(entityToModel(entity));
}
Collections.sort(actions, RequiredActionProviderModel.RequiredActionComparator.SINGLETON);
return Collections.unmodifiableList(actions);
public Stream<RequiredActionProviderModel> getRequiredActionProvidersStream() {
return realm.getRequiredActionProviders().stream()
.map(this::entityToModel)
.sorted(RequiredActionProviderModel.RequiredActionComparator.SINGLETON);
}
private RequiredActionProviderEntity getRequiredProviderEntity(String id, boolean readForRemove) {
@ -1995,10 +1926,10 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
@Override
public RequiredActionProviderModel getRequiredActionProviderByAlias(String alias) {
for (RequiredActionProviderModel action : getRequiredActionProviders()) {
if (action.getAlias().equals(alias)) return action;
}
return null;
return getRequiredActionProvidersStream()
.filter(action -> Objects.equals(action.getAlias(), alias))
.findFirst()
.orElse(null);
}
@Override
@ -2052,14 +1983,8 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
}
@Override
public List<ClientScopeModel> getClientScopes() {
Collection<ClientScopeEntity> entities = realm.getClientScopes();
if (entities == null || entities.isEmpty()) return Collections.EMPTY_LIST;
List<ClientScopeModel> list = new LinkedList<>();
for (ClientScopeEntity entity : entities) {
list.add(session.realms().getClientScopeById(entity.getId(), this));
}
return Collections.unmodifiableList(list);
public Stream<ClientScopeModel> getClientScopesStream() {
return realm.getClientScopes().stream().map(ClientScopeEntity::getId).map(this::getClientScopeById);
}
@Override
@ -2142,19 +2067,11 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
}
@Override
public List<ClientScopeModel> getDefaultClientScopes(boolean defaultScope) {
public Stream<ClientScopeModel> getDefaultClientScopesStream(boolean defaultScope) {
TypedQuery<String> query = em.createNamedQuery("defaultClientScopeRealmMappingIdsByRealm", String.class);
query.setParameter("realm", getEntity());
query.setParameter("defaultScope", defaultScope);
List<String> ids = query.getResultList();
List<ClientScopeModel> clientScopes = new LinkedList<>();
for (String clientScopeId : ids) {
ClientScopeModel clientScope = getClientScopeById(clientScopeId);
if (clientScope == null) continue;
clientScopes.add(clientScope);
}
return clientScopes;
return closing(query.getResultStream().map(this::getClientScopeById).filter(Objects::nonNull));
}
@Override
@ -2273,23 +2190,22 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
}
@Override
public List<ComponentModel> getComponents(String parentId, final String providerType) {
public Stream<ComponentModel> getComponentsStream(String parentId, final String providerType) {
if (parentId == null) parentId = getId();
final String parent = parentId;
return realm.getComponents().stream()
.filter(c -> parent.equals(c.getParentId())
&& providerType.equals(c.getProviderType()))
.map(this::entityToModel)
.collect(Collectors.toList());
Stream<ComponentEntity> componentStream = realm.getComponents().stream()
.filter(c -> Objects.equals(parent, c.getParentId()));
if (providerType != null) {
componentStream = componentStream.filter(c -> Objects.equals(providerType, c.getProviderType()));
}
return componentStream.map(this::entityToModel);
}
@Override
public List<ComponentModel> getComponents(final String parentId) {
return realm.getComponents().stream()
.filter(c -> parentId.equals(c.getParentId()))
.map(this::entityToModel)
.collect(Collectors.toList());
public Stream<ComponentModel> getComponentsStream(final String parentId) {
return getComponentsStream(parentId, null);
}
protected ComponentModel entityToModel(ComponentEntity c) {
@ -2308,9 +2224,18 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
return model;
}
private RequiredCredentialModel toRequiredCredentialModel(RequiredCredentialEntity entity) {
RequiredCredentialModel model = new RequiredCredentialModel();
model.setFormLabel(entity.getFormLabel());
model.setType(entity.getType());
model.setSecret(entity.isSecret());
model.setInput(entity.isInput());
return model;
}
@Override
public List<ComponentModel> getComponents() {
return realm.getComponents().stream().map(this::entityToModel).collect(Collectors.toList());
public Stream<ComponentModel> getComponentsStream() {
return realm.getComponents().stream().map(this::entityToModel);
}
@Override

View file

@ -27,9 +27,10 @@ import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -57,17 +58,19 @@ public class EventBuilder {
}
}
if (realm.getEventsListeners() != null && !realm.getEventsListeners().isEmpty()) {
this.listeners = new LinkedList<>();
for (String id : realm.getEventsListeners()) {
EventListenerProvider listener = session.getProvider(EventListenerProvider.class, id);
if (listener != null) {
listeners.add(listener);
} else {
log.error("Event listener '" + id + "' registered, but provider not found");
}
}
}
this.listeners = realm.getEventsListenersStream()
.map(id -> {
EventListenerProvider listener = session.getProvider(EventListenerProvider.class, id);
if (listener != null) {
return listener;
} else {
log.error("Event listener '" + id + "' registered, but provider not found");
return null;
}
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
realm(realm);
ipAddress(clientConnection.getRemoteAddr());
@ -177,7 +180,8 @@ public class EventBuilder {
event.setTime(Time.currentTimeMillis());
if (store != null) {
if (realm.getEnabledEventTypes() != null && !realm.getEnabledEventTypes().isEmpty() ? realm.getEnabledEventTypes().contains(event.getType().name()) : event.getType().isSaveByDefault()) {
Set<String> eventTypes = realm.getEnabledEventTypesStream().collect(Collectors.toSet());
if (!eventTypes.isEmpty() ? eventTypes.contains(event.getType().name()) : event.getType().isSaveByDefault()) {
try {
store.onEvent(event);
} catch (Throwable t) {

View file

@ -19,6 +19,8 @@ package org.keycloak.events;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -43,6 +45,17 @@ public interface EventQuery {
EventQuery maxResults(int results);
List<Event> getResultList();
/**
* @deprecated Use {@link #getResultStream() getResultStream} instead.
*/
@Deprecated
default List<Event> getResultList() {
return getResultStream().collect(Collectors.toList());
}
/**
* Returns requested results that match given criteria as a stream.
* @return Stream of events
*/
Stream<Event> getResultStream();
}

View file

@ -19,6 +19,8 @@ package org.keycloak.events.admin;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -127,8 +129,16 @@ public interface AdminEventQuery {
/**
* Executes the query and returns the results
*
* @return
* @deprecated Use {@link #getResultStream() getResultStream} instead.
*/
List<AdminEvent> getResultList();
@Deprecated
default List<AdminEvent> getResultList() {
return getResultStream().collect(Collectors.toList());
}
/**
* Executes the query and returns the results as a stream.
* @return Stream of admin events
*/
Stream<AdminEvent> getResultStream();
}

View file

@ -26,8 +26,6 @@ import org.keycloak.models.RoleModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.idm.RealmRepresentation;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
@ -68,12 +66,10 @@ public class MigrateTo1_2_0 implements Migration {
}
public void migrate(KeycloakSession session) {
List<RealmModel> realms = session.realms().getRealms();
for (RealmModel realm : realms) {
session.realms().getRealmsStream().forEach(realm -> {
setupBrokerService(realm);
setupClientNames(realm);
}
});
}
@Override

View file

@ -19,7 +19,6 @@ package org.keycloak.migration.migrators;
import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.component.ComponentFactory;
import org.keycloak.component.ComponentModel;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.LDAPConstants;
@ -44,11 +43,7 @@ public class MigrateTo1_3_0 implements Migration {
}
public void migrate(KeycloakSession session) {
List<RealmModel> realms = session.realms().getRealms();
for (RealmModel realm : realms) {
migrateLDAPProviders(session, realm);
}
session.realms().getRealmsStream().forEach(realm -> migrateLDAPProviders(session, realm));
}
@Override
@ -57,9 +52,7 @@ public class MigrateTo1_3_0 implements Migration {
}
private void migrateLDAPProviders(KeycloakSession session, RealmModel realm) {
List<UserStorageProviderModel> federationProviders = realm.getUserStorageProviders();
for (UserStorageProviderModel fedProvider : federationProviders) {
realm.getUserStorageProvidersStream().forEachOrdered(fedProvider -> {
if (fedProvider.getProviderId().equals(LDAPConstants.LDAP_PROVIDER)) {
fedProvider = new UserStorageProviderModel(fedProvider); // copy don't want to muck with cache
MultivaluedHashMap<String, String> config = fedProvider.getConfig();
@ -91,14 +84,13 @@ public class MigrateTo1_3_0 implements Migration {
realm.updateComponent(fedProvider);
// Create default mappers for LDAP
List<ComponentModel> mappers = realm.getComponents(fedProvider.getId());
if (mappers.isEmpty()) {
if (realm.getComponentsStream(fedProvider.getId()).count() == 0) {
ProviderFactory ldapFactory = session.getKeycloakSessionFactory().getProviderFactory(UserStorageProvider.class, LDAPConstants.LDAP_PROVIDER);
if (ldapFactory != null) {
((ComponentFactory) ldapFactory).onCreate(session, realm, fedProvider);
}
}
}
}
});
}
}

View file

@ -29,10 +29,10 @@ import org.keycloak.models.utils.DefaultAuthenticationFlows;
import org.keycloak.models.utils.DefaultRequiredActions;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.storage.UserStorageProviderModel;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -45,15 +45,11 @@ public class MigrateTo1_4_0 implements Migration {
}
public void migrate(KeycloakSession session) {
List<RealmModel> realms = session.realms().getRealms();
for (RealmModel realm : realms) {
migrateRealm(session, realm);
}
session.realms().getRealmsStream().forEach(realm -> migrateRealm(session, realm));
}
protected void migrateRealm(KeycloakSession session, RealmModel realm) {
if (realm.getAuthenticationFlows().size() == 0) {
if (realm.getAuthenticationFlowsStream().count() == 0) {
DefaultAuthenticationFlows.migrateFlows(realm);
DefaultRequiredActions.addActions(realm);
}
@ -71,19 +67,15 @@ public class MigrateTo1_4_0 implements Migration {
private void migrateLDAPMappers(KeycloakSession session, RealmModel realm) {
List<String> mandatoryInLdap = Arrays.asList("username", "username-cn", "first name", "last name");
for (UserStorageProviderModel providerModel : realm.getUserStorageProviders()) {
if (providerModel.getProviderId().equals(LDAPConstants.LDAP_PROVIDER)) {
List<ComponentModel> mappers = realm.getComponents(providerModel.getId());
for (ComponentModel mapper : mappers) {
if (mandatoryInLdap.contains(mapper.getName())) {
mapper = new ComponentModel(mapper); // don't want to modify cache
mapper.getConfig().putSingle("is.mandatory.in.ldap", "true");
realm.updateComponent(mapper);
}
}
}
}
realm.getUserStorageProvidersStream()
.filter(providerModel -> Objects.equals(providerModel.getProviderId(), LDAPConstants.LDAP_PROVIDER))
.forEachOrdered(providerModel -> realm.getComponentsStream(providerModel.getId())
.filter(mapper -> mandatoryInLdap.contains(mapper.getName()))
.forEach(mapper -> {
mapper = new ComponentModel(mapper); // don't want to modify cache
mapper.getConfig().putSingle("is.mandatory.in.ldap", "true");
realm.updateComponent(mapper);
}));
}
private void migrateUsers(KeycloakSession session, RealmModel realm) {

View file

@ -25,8 +25,6 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.DefaultAuthenticationFlows;
import org.keycloak.representations.idm.RealmRepresentation;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
@ -39,11 +37,7 @@ public class MigrateTo1_5_0 implements Migration {
}
public void migrate(KeycloakSession session) {
List<RealmModel> realms = session.realms().getRealms();
for (RealmModel realm : realms) {
migrateRealm(session, realm);
}
session.realms().getRealmsStream().forEach(realm -> migrateRealm(session, realm));
}
@Override

View file

@ -29,8 +29,6 @@ import org.keycloak.models.RoleModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.idm.RealmRepresentation;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@ -51,10 +49,7 @@ public class MigrateTo1_6_0 implements Migration {
throw new RuntimeException("Can't find default locale mapper");
}
List<RealmModel> realms = session.realms().getRealms();
for (RealmModel realm : realms) {
migrateRealm(session, localeMapper, realm);
}
session.realms().getRealmsStream().forEach(realm -> migrateRealm(session, localeMapper, realm));
}
@Override

View file

@ -21,14 +21,11 @@ import org.keycloak.migration.MigrationProvider;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.AuthenticationFlowModel;
import org.keycloak.models.Constants;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.DefaultAuthenticationFlows;
import org.keycloak.representations.idm.RealmRepresentation;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@ -41,11 +38,7 @@ public class MigrateTo1_7_0 implements Migration {
}
public void migrate(KeycloakSession session) {
List<RealmModel> realms = session.realms().getRealms();
for (RealmModel realm : realms) {
migrateRealm(session, realm);
}
session.realms().getRealmsStream().forEach(realm -> migrateRealm(session, realm));
}
@Override
@ -65,12 +58,11 @@ public class MigrateTo1_7_0 implements Migration {
DefaultAuthenticationFlows.migrateFlows(realm);
AuthenticationFlowModel firstBrokerLoginFlow = realm.getFlowByAlias(DefaultAuthenticationFlows.FIRST_BROKER_LOGIN_FLOW);
List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
for (IdentityProviderModel identityProvider : identityProviders) {
if (identityProvider.getFirstBrokerLoginFlowId() == null) {
identityProvider.setFirstBrokerLoginFlowId(firstBrokerLoginFlow.getId());
realm.updateIdentityProvider(identityProvider);
}
}
realm.getIdentityProvidersStream()
.filter(provider -> provider.getFirstBrokerLoginFlowId() == null)
.forEach(provider -> {
provider.setFirstBrokerLoginFlowId(firstBrokerLoginFlow.getId());
realm.updateIdentityProvider(provider);
});
}
}

View file

@ -26,7 +26,7 @@ import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.storage.UserStorageProviderModel;
import java.util.List;
import java.util.Objects;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@ -41,12 +41,7 @@ public class MigrateTo1_8_0 implements Migration {
public void migrate(KeycloakSession session) {
List<RealmModel> realms = session.realms().getRealms();
for (RealmModel realm : realms) {
migrateRealm(realm);
}
session.realms().getRealmsStream().forEach(this::migrateRealm);
}
@Override
@ -55,30 +50,22 @@ public class MigrateTo1_8_0 implements Migration {
}
protected void migrateRealm(RealmModel realm) {
List<UserStorageProviderModel> federationProviders = realm.getUserStorageProviders();
for (UserStorageProviderModel fedProvider : federationProviders) {
if (fedProvider.getProviderId().equals(LDAPConstants.LDAP_PROVIDER)) {
if (isActiveDirectory(fedProvider)) {
// Create mapper for MSAD account controls
if (getMapperByName(realm, fedProvider, "MSAD account controls") == null) {
ComponentModel mapperModel = KeycloakModelUtils.createComponentModel("MSAD account controls", fedProvider.getId(), LDAPConstants.MSAD_USER_ACCOUNT_CONTROL_MAPPER, "org.keycloak.storage.ldap.mappers.LDAPStorageMapper");
realm.addComponentModel(mapperModel);
}
}
}
}
realm.getUserStorageProvidersStream()
.filter(fedProvider -> Objects.equals(fedProvider.getProviderId(), LDAPConstants.LDAP_PROVIDER))
.filter(this::isActiveDirectory)
.filter(fedProvider -> Objects.isNull(getMapperByName(realm, fedProvider, "MSAD account controls")))
// Create mapper for MSAD account controls
.map(fedProvider -> KeycloakModelUtils.createComponentModel("MSAD account controls",
fedProvider.getId(), LDAPConstants.MSAD_USER_ACCOUNT_CONTROL_MAPPER,
"org.keycloak.storage.ldap.mappers.LDAPStorageMapper"))
.forEachOrdered(realm::addComponentModel);
}
public static ComponentModel getMapperByName(RealmModel realm, ComponentModel providerModel, String name) {
List<ComponentModel> components = realm.getComponents(providerModel.getId(), "org.keycloak.storage.ldap.mappers.LDAPStorageMapper");
for (ComponentModel component : components) {
if (component.getName().equals(name)) {
return component;
}
}
return null;
return realm.getComponentsStream(providerModel.getId(), "org.keycloak.storage.ldap.mappers.LDAPStorageMapper")
.filter(component -> Objects.equals(component.getName(), name))
.findFirst()
.orElse(null);
}

View file

@ -35,9 +35,7 @@ public class MigrateTo1_9_2 implements Migration {
}
public void migrate(KeycloakSession session) {
for (RealmModel realm : session.realms().getRealms()) {
migrateRealm(realm);
}
session.realms().getRealmsStream().forEach(this::migrateRealm);
}
@Override

View file

@ -33,9 +33,7 @@ public class MigrateTo2_0_0 implements Migration {
}
public void migrate(KeycloakSession session) {
for (RealmModel realm : session.realms().getRealms()) {
migrateAuthorizationServices(realm);
}
session.realms().getRealmsStream().forEach(this::migrateAuthorizationServices);
}
@Override

View file

@ -47,10 +47,10 @@ public class MigrateTo2_1_0 implements Migration {
}
public void migrate(KeycloakSession session) {
for (RealmModel realm : session.realms().getRealms()) {
session.realms().getRealmsStream().forEach(realm -> {
migrateDefaultRequiredAction(realm);
migrateRolePolicies(realm, session);
}
});
}
@Override

View file

@ -35,9 +35,7 @@ public class MigrateTo2_2_0 implements Migration {
}
public void migrate(KeycloakSession session) {
for (RealmModel realm : session.realms().getRealms()) {
addIdentityProviderAuthenticator(realm);
}
session.realms().getRealmsStream().forEach(this::addIdentityProviderAuthenticator);
}
@Override
@ -47,13 +45,12 @@ public class MigrateTo2_2_0 implements Migration {
}
private void addIdentityProviderAuthenticator(RealmModel realm) {
String defaultProvider = null;
for (IdentityProviderModel provider : realm.getIdentityProviders()) {
if (provider.isEnabled() && provider.isAuthenticateByDefault()) {
defaultProvider = provider.getAlias();
break;
}
}
String defaultProvider = realm.getIdentityProvidersStream()
.filter(IdentityProviderModel::isEnabled)
.filter(IdentityProviderModel::isAuthenticateByDefault)
.map(IdentityProviderModel::getAlias)
.findFirst()
.orElse(null);
DefaultAuthenticationFlows.addIdentityProviderAuthenticator(realm, defaultProvider);
}

View file

@ -19,7 +19,6 @@ package org.keycloak.migration.migrators;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.representations.idm.RealmRepresentation;
@ -33,17 +32,13 @@ public class MigrateTo2_3_0 implements Migration {
@Override
public void migrate(KeycloakSession session) {
for (RealmModel realm : session.realms().getRealms()) {
migrateRealm(realm);
}
session.realms().getRealmsStream().forEach(this::migrateRealm);
}
protected void migrateRealm(RealmModel realm) {
realm.getClientsStream().forEach(MigrationUtils::updateProtocolMappers);
for (ClientScopeModel clientScope : realm.getClientScopes()) {
MigrationUtils.updateProtocolMappers(clientScope);
}
realm.getClientScopesStream().forEach(MigrationUtils::updateProtocolMappers);
}
@Override

View file

@ -33,9 +33,7 @@ public class MigrateTo2_5_0 implements Migration {
@Override
public void migrate(KeycloakSession session) {
session.realms().getRealms().stream().forEach(
r -> DefaultKeyProviders.createSecretProvider(r)
);
session.realms().getRealmsStream().forEach(DefaultKeyProviders::createSecretProvider);
}
@Override

View file

@ -41,12 +41,7 @@ public class MigrateTo3_0_0 implements Migration {
@Override
public void migrate(KeycloakSession session) {
for (RealmModel realm : session.realms().getRealms()) {
migrateRealm(realm);
}
session.realms().getRealmsStream().forEach(this::migrateRealm);
}
@Override

View file

@ -36,9 +36,7 @@ public class MigrateTo3_1_0 implements Migration {
@Override
public void migrate(KeycloakSession session) {
for (RealmModel realm : session.realms().getRealms()) {
migrateRealm(realm);
}
session.realms().getRealmsStream().forEach(this::migrateRealm);
}
protected void migrateRealm(RealmModel realm) {

View file

@ -33,10 +33,7 @@ public class MigrateTo3_2_0 implements Migration {
@Override
public void migrate(KeycloakSession session) {
for (RealmModel realm : session.realms().getRealms()) {
migrateRealm(session, realm);
}
session.realms().getRealmsStream().forEach(realm -> migrateRealm(session, realm));
}
@Override

View file

@ -17,7 +17,6 @@
package org.keycloak.migration.migrators;
import org.keycloak.keys.KeyProvider;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
@ -37,11 +36,7 @@ public class MigrateTo3_4_0 implements Migration {
@Override
public void migrate(KeycloakSession session) {
session.realms().getRealms().stream().forEach(
r -> {
migrateRealm(r);
}
);
session.realms().getRealmsStream().forEach(this::migrateRealm);
}
@Override

View file

@ -37,11 +37,7 @@ public class MigrateTo3_4_1 implements Migration {
@Override
public void migrate(KeycloakSession session) {
session.realms().getRealms().stream().forEach(
r -> {
migrateRealm(r);
}
);
session.realms().getRealmsStream().forEach(this::migrateRealm);
}
@Override

View file

@ -36,11 +36,7 @@ public class MigrateTo3_4_2 implements Migration {
@Override
public void migrate(KeycloakSession session) {
session.realms().getRealms().stream().forEach(
r -> {
migrateRealm(r);
}
);
session.realms().getRealmsStream().forEach(this::migrateRealm);
}
@Override

View file

@ -18,10 +18,10 @@
package org.keycloak.migration.migrators;
import java.util.List;
import java.util.Objects;
import org.jboss.logging.Logger;
import org.keycloak.OAuth2Constants;
import org.keycloak.component.ComponentModel;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientScopeModel;
@ -48,11 +48,7 @@ public class MigrateTo4_0_0 implements Migration {
@Override
public void migrate(KeycloakSession session) {
session.realms().getRealms().stream().forEach(
r -> {
migrateRealm(session, r, false);
}
);
session.realms().getRealmsStream().forEach(realm -> migrateRealm(session, realm, false));
}
@Override
@ -63,13 +59,14 @@ public class MigrateTo4_0_0 implements Migration {
protected void migrateRealm(KeycloakSession session, RealmModel realm, boolean json) {
// Upgrade names of clientScopes to not contain space
for (ClientScopeModel clientScope : realm.getClientScopes()) {
if (clientScope.getName().contains(" ")) {
LOG.debugf("Replacing spaces with underscores in the name of client scope '%s' of realm '%s'", clientScope.getName(), realm.getName());
String replacedName = clientScope.getName().replaceAll(" ", "_");
clientScope.setName(replacedName);
}
}
realm.getClientScopesStream()
.filter(clientScope -> clientScope.getName().contains(" "))
.forEach(clientScope -> {
LOG.debugf("Replacing spaces with underscores in the name of client scope '%s' of realm '%s'",
clientScope.getName(), realm.getName());
String replacedName = clientScope.getName().replaceAll(" ", "_");
clientScope.setName(replacedName);
});
if (!json) {
// Add default client scopes. But don't add them to existing clients. For JSON, they were already added
@ -78,17 +75,17 @@ public class MigrateTo4_0_0 implements Migration {
}
// Upgrade configuration of "allowed-client-templates" client registration policy
for (ComponentModel component : realm.getComponents(realm.getId(), "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy")) {
if ("allowed-client-templates".equals(component.getProviderId())) {
List<String> configVal = component.getConfig().remove("allowed-client-templates");
if (configVal != null) {
component.getConfig().put("allowed-client-scopes", configVal);
}
component.put("allow-default-scopes", true);
realm.getComponentsStream(realm.getId(), "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy")
.filter(component -> Objects.equals(component.getProviderId(), "allowed-client-templates"))
.forEach(component -> {
List<String> configVal = component.getConfig().remove("allowed-client-templates");
if (configVal != null) {
component.getConfig().put("allowed-client-scopes", configVal);
}
component.put("allow-default-scopes", true);
realm.updateComponent(component);
}
}
realm.updateComponent(component);
});
// If client has scope for offline_access role (either directly or through fullScopeAllowed), then add offline_access client

View file

@ -19,8 +19,7 @@ package org.keycloak.migration.migrators;
import static java.util.Comparator.comparing;
import java.util.List;
import java.util.stream.Collectors;
import java.util.concurrent.atomic.AtomicInteger;
import org.jboss.logging.Logger;
import org.keycloak.migration.ModelVersion;
@ -45,29 +44,27 @@ public class MigrateTo4_2_0 implements Migration {
@Override
public void migrate(KeycloakSession session) {
session.realms().getRealms().stream().forEach(r -> {
migrateRealm(session, r, false);
});
session.realms().getRealmsStream().forEach(this::migrateRealm);
}
@Override
public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
migrateRealm(session, realm, true);
migrateRealm(realm);
}
protected void migrateRealm(KeycloakSession session, RealmModel realm, boolean json) {
protected void migrateRealm(RealmModel realm) {
// Set default priority of required actions in alphabetical order
List<RequiredActionProviderModel> actions = realm.getRequiredActionProviders().stream()
.sorted(comparing(RequiredActionProviderModel::getName)).collect(Collectors.toList());
int priority = 10;
for (RequiredActionProviderModel model : actions) {
LOG.debugf("Setting priority '%d' for required action '%s' in realm '%s'", priority, model.getAlias(),
realm.getName());
model.setPriority(priority);
priority += 10;
AtomicInteger priority = new AtomicInteger(10);
realm.getRequiredActionProvidersStream()
.sorted(comparing(RequiredActionProviderModel::getName))
.forEachOrdered(model -> {
LOG.debugf("Setting priority '%d' for required action '%s' in realm '%s'", priority.get(), model.getAlias(),
realm.getName());
model.setPriority(priority.get());
priority.addAndGet(10);
// Save
realm.updateRequiredActionProvider(model);
}
// Save
realm.updateRequiredActionProvider(model);
});
}
}

View file

@ -42,9 +42,7 @@ public class MigrateTo4_6_0 implements Migration {
@Override
public void migrate(KeycloakSession session) {
session.realms().getRealms().stream().forEach(r -> {
migrateRealm(session, r, false);
});
session.realms().getRealmsStream().forEach(realm -> migrateRealm(session, realm, false));
}
@Override

View file

@ -43,9 +43,7 @@ public class MigrateTo6_0_0 implements Migration {
@Override
public void migrate(KeycloakSession session) {
session.realms().getRealms().stream().forEach(r -> {
migrateRealm(session, r, false);
});
session.realms().getRealmsStream().forEach(realm -> migrateRealm(session, realm, false));
}
@Override

View file

@ -46,11 +46,9 @@ public class MigrateTo8_0_0 implements Migration {
@Override
public void migrate(KeycloakSession session) {
// Perform basic realm migration first (non multi-factor authentication)
session.realms().getRealms().stream().forEach(realm -> migrateRealmCommon(realm));
session.realms().getRealmsStream().forEach(this::migrateRealmCommon);
// Moreover, for multi-factor authentication migrate optional execution of realm flows to subflows
session.realms().getRealms().stream().forEach(r -> {
migrateRealmMFA(session, r, false);
});
session.realms().getRealmsStream().forEach(realm -> migrateRealmMFA(realm));
}
@Override
@ -79,15 +77,12 @@ public class MigrateTo8_0_0 implements Migration {
}
}
protected void migrateRealmMFA(KeycloakSession session, RealmModel realm, boolean jsn) {
for (AuthenticationFlowModel authFlow : realm.getAuthenticationFlows()) {
for (AuthenticationExecutionModel authExecution : realm.getAuthenticationExecutions(authFlow.getId())) {
// Those were OPTIONAL executions in previous version
if (authExecution.getRequirement() == AuthenticationExecutionModel.Requirement.CONDITIONAL) {
migrateOptionalAuthenticationExecution(realm, authFlow, authExecution, true);
}
}
}
protected void migrateRealmMFA(RealmModel realm) {
realm.getAuthenticationFlowsStream()
.forEach(authFlow ->
realm.getAuthenticationExecutionsStream(authFlow.getId())
.filter(exe -> exe.getRequirement() == AuthenticationExecutionModel.Requirement.CONDITIONAL)
.forEachOrdered(exe -> migrateOptionalAuthenticationExecution(realm, authFlow, exe, true)));
}
public static void migrateOptionalAuthenticationExecution(RealmModel realm, AuthenticationFlowModel parentFlow, AuthenticationExecutionModel optionalExecution, boolean updateOptionalExecution) {

View file

@ -19,6 +19,10 @@
package org.keycloak.migration.migrators;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import org.jboss.logging.Logger;
import org.keycloak.migration.ModelVersion;
@ -28,6 +32,8 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.representations.idm.RealmRepresentation;
import static org.keycloak.models.AuthenticationExecutionModel.Requirement.*;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@ -44,7 +50,7 @@ public class MigrateTo8_0_2 implements Migration {
@Override
public void migrate(KeycloakSession session) {
session.realms().getRealms().forEach(this::migrateAuthenticationFlowsWithAlternativeRequirements);
session.realms().getRealmsStream().forEach(this::migrateAuthenticationFlowsWithAlternativeRequirements);
}
@Override
@ -54,47 +60,39 @@ public class MigrateTo8_0_2 implements Migration {
protected void migrateAuthenticationFlowsWithAlternativeRequirements(RealmModel realm) {
for (AuthenticationFlowModel flow : realm.getAuthenticationFlows()) {
for (AuthenticationFlowModel flow : realm.getAuthenticationFlowsStream().collect(Collectors.toList())) {
List<AuthenticationExecutionModel> executions = realm.getAuthenticationExecutionsStream(flow.getId())
.collect(Collectors.toList());
boolean alternativeFound = false;
boolean requiredFound = false;
for (AuthenticationExecutionModel execution : realm.getAuthenticationExecutions(flow.getId())) {
switch (execution.getRequirement()) {
case REQUIRED:
case CONDITIONAL:
requiredFound = true;
break;
case ALTERNATIVE:
alternativeFound = true;
break;
}
}
Set<AuthenticationExecutionModel.Requirement> requirements = executions.stream()
.map(AuthenticationExecutionModel::getRequirement)
.collect(Collectors.toSet());
// This flow contains some REQUIRED and ALTERNATIVE at the same level. We will migrate ALTERNATIVES to separate subflows
// to try to preserve same behaviour as in previous versions
if (requiredFound && alternativeFound) {
if (requirements.contains(REQUIRED) || requirements.contains(CONDITIONAL) && requirements.contains(ALTERNATIVE)) {
// Suffix used just to avoid name conflicts
int suffix = 0;
AtomicInteger suffix = new AtomicInteger(0);
LinkedList<AuthenticationExecutionModel> alternativesToMigrate = new LinkedList<>();
for (AuthenticationExecutionModel execution : realm.getAuthenticationExecutions(flow.getId())) {
for (AuthenticationExecutionModel execution: executions) {
if (AuthenticationExecutionModel.Requirement.ALTERNATIVE.equals(execution.getRequirement())) {
alternativesToMigrate.add(execution);
}
// If we have some REQUIRED then ALTERNATIVE and then REQUIRED/CONDITIONAL, we migrate the alternatives to the new subflow.
if (AuthenticationExecutionModel.Requirement.REQUIRED.equals(execution.getRequirement()) ||
AuthenticationExecutionModel.Requirement.CONDITIONAL.equals(execution.getRequirement())) {
if (REQUIRED.equals(execution.getRequirement()) ||
CONDITIONAL.equals(execution.getRequirement())) {
if (!alternativesToMigrate.isEmpty()) {
migrateAlternatives(realm, flow, alternativesToMigrate, suffix);
suffix += 1;
migrateAlternatives(realm, flow, alternativesToMigrate, suffix.get());
suffix.addAndGet(1);
alternativesToMigrate.clear();
}
}
}
if (!alternativesToMigrate.isEmpty()) {
migrateAlternatives(realm, flow, alternativesToMigrate, suffix);
migrateAlternatives(realm, flow, alternativesToMigrate, suffix.get());
}
}
}
@ -116,7 +114,7 @@ public class MigrateTo8_0_2 implements Migration {
AuthenticationExecutionModel execution = new AuthenticationExecutionModel();
execution.setParentFlow(parentFlow.getId());
execution.setRequirement(AuthenticationExecutionModel.Requirement.REQUIRED);
execution.setRequirement(REQUIRED);
execution.setFlowId(newFlow.getId());
// Use same priority as the first ALTERNATIVE as new execution will defacto replace it in the parent flow
execution.setPriority(alternativesToMigrate.getFirst().getPriority());

View file

@ -47,7 +47,7 @@ public class MigrateTo9_0_0 implements Migration {
@Override
public void migrate(KeycloakSession session) {
session.realms().getRealms().stream().forEach(realm -> migrateRealmCommon(realm));
session.realms().getRealmsStream().forEach(this::migrateRealmCommon);
}
@Override

View file

@ -38,7 +38,7 @@ public class MigrateTo9_0_4 implements Migration {
@Override
public void migrate(KeycloakSession session) {
session.realms().getRealms().stream().forEach(this::checkAuthConfigNullAlias);
session.realms().getRealmsStream().forEach(this::checkAuthConfigNullAlias);
}
@Override
@ -46,7 +46,7 @@ public class MigrateTo9_0_4 implements Migration {
}
protected void checkAuthConfigNullAlias(RealmModel realm) {
realm.getAuthenticatorConfigs().stream()
realm.getAuthenticatorConfigsStream()
.filter(this::hasNullAlias)
.forEach((config) -> this.setRandomAlias(realm, config));
}

View file

@ -24,10 +24,7 @@ import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredCredentialModel;
import org.keycloak.representations.idm.IdentityProviderRepresentation;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -150,13 +147,7 @@ public class DefaultAuthenticationFlows {
}
private static boolean hasCredentialType(RealmModel realm, String type) {
for (RequiredCredentialModel requiredCredentialModel : realm.getRequiredCredentials()) {
if (type.equals(requiredCredentialModel.getType())) {
return true;
}
}
return false;
return realm.getRequiredCredentialsStream().anyMatch(r -> Objects.equals(r.getType(), type));
}
public static void resetCredentialsFlow(RealmModel realm) {
@ -388,20 +379,16 @@ public class DefaultAuthenticationFlows {
}
public static void addIdentityProviderAuthenticator(RealmModel realm, String defaultProvider) {
String browserFlowId = null;
for (AuthenticationFlowModel f : realm.getAuthenticationFlows()) {
if (f.getAlias().equals(DefaultAuthenticationFlows.BROWSER_FLOW)) {
browserFlowId = f.getId();
break;
}
}
String browserFlowId = realm.getAuthenticationFlowsStream()
.filter(f -> Objects.equals(f.getAlias(), DefaultAuthenticationFlows.BROWSER_FLOW))
.map(AuthenticationFlowModel::getId)
.findFirst()
.orElse(null);
if (browserFlowId != null) {
for (AuthenticationExecutionModel e : realm.getAuthenticationExecutions(browserFlowId)) {
if ("identity-provider-redirector".equals(e.getAuthenticator())) {
return;
}
}
if (realm.getAuthenticationExecutionsStream(browserFlowId)
.anyMatch(e -> Objects.equals(e.getAuthenticator(), "identity-provider-redirector")))
return;
AuthenticationExecutionModel execution;
execution = new AuthenticationExecutionModel();
@ -618,7 +605,8 @@ public class DefaultAuthenticationFlows {
KeycloakModelUtils.deepFindAuthenticationExecutions(realm, browserFlow, browserExecutions);
for (AuthenticationExecutionModel browserExecution : browserExecutions) {
if (browserExecution.isAuthenticatorFlow()){
if (realm.getAuthenticationExecutions(browserExecution.getFlowId()).stream().anyMatch(e -> e.getAuthenticator().equals("auth-otp-form"))){
if (realm.getAuthenticationExecutionsStream(browserExecution.getFlowId())
.anyMatch(e -> e.getAuthenticator().equals("auth-otp-form"))){
execution.setRequirement(browserExecution.getRequirement());
}
}

View file

@ -23,7 +23,7 @@ import org.keycloak.crypto.Algorithm;
import org.keycloak.keys.KeyProvider;
import org.keycloak.models.RealmModel;
import java.util.List;
import java.util.Objects;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -81,13 +81,8 @@ public class DefaultKeyProviders {
}
protected static boolean hasProvider(RealmModel realm, String providerId) {
List<ComponentModel> currentComponents = realm.getComponents(realm.getId(), KeyProvider.class.getName());
for (ComponentModel current : currentComponents) {
if (current.getProviderId().equals(providerId)) {
return true;
}
}
return false;
return realm.getComponentsStream(realm.getId(), KeyProvider.class.getName())
.anyMatch(component -> Objects.equals(component.getProviderId(), providerId));
}
public static void createProviders(RealmModel realm, String privateKeyPem, String certificatePem) {

View file

@ -35,7 +35,6 @@ import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.KeycloakSessionTask;
import org.keycloak.models.KeycloakTransaction;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleContainerModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.ScopeContainerModel;
import org.keycloak.models.UserCredentialModel;
@ -296,21 +295,17 @@ public final class KeycloakModelUtils {
return null;
}
for (UserStorageProviderModel fedProvider : realm.getUserStorageProviders()) {
if (displayName.equals(fedProvider.getName())) {
return fedProvider;
}
}
return null;
return realm.getUserStorageProvidersStream()
.filter(fedProvider -> Objects.equals(fedProvider.getName(), displayName))
.findFirst()
.orElse(null);
}
public static UserStorageProviderModel findUserStorageProviderById(String fedProviderId, RealmModel realm) {
for (UserStorageProviderModel fedProvider : realm.getUserStorageProviders()) {
if (fedProviderId.equals(fedProvider.getId())) {
return fedProvider;
}
}
return null;
return realm.getUserStorageProvidersStream()
.filter(fedProvider -> Objects.equals(fedProvider.getId(), fedProviderId))
.findFirst()
.orElse(null);
}
public static ComponentModel createComponentModel(String name, String parentId, String providerId, String providerType, String... config) {
@ -364,15 +359,14 @@ public final class KeycloakModelUtils {
* @param result input should be empty list. At the end will be all executions added to this list
*/
public static void deepFindAuthenticationExecutions(RealmModel realm, AuthenticationFlowModel flow, List<AuthenticationExecutionModel> result) {
List<AuthenticationExecutionModel> executions = realm.getAuthenticationExecutions(flow.getId());
for (AuthenticationExecutionModel execution : executions) {
realm.getAuthenticationExecutionsStream(flow.getId()).forEachOrdered(execution -> {
if (execution.isAuthenticatorFlow()) {
AuthenticationFlowModel subFlow = realm.getAuthenticationFlowById(execution.getFlowId());
deepFindAuthenticationExecutions(realm, subFlow, result);
} else {
result.add(execution);
}
}
});
}
public static String resolveFirstAttribute(GroupModel group, String name) {
@ -575,13 +569,9 @@ public final class KeycloakModelUtils {
if ((realmFlow = realm.getResetCredentialsFlow()) != null && realmFlow.getId().equals(model.getId())) return true;
if ((realmFlow = realm.getDockerAuthenticationFlow()) != null && realmFlow.getId().equals(model.getId())) return true;
for (IdentityProviderModel idp : realm.getIdentityProviders()) {
if (model.getId().equals(idp.getFirstBrokerLoginFlowId())) return true;
if (model.getId().equals(idp.getPostBrokerLoginFlowId())) return true;
}
return false;
return realm.getIdentityProvidersStream().anyMatch(idp ->
Objects.equals(idp.getFirstBrokerLoginFlowId(), model.getId()) ||
Objects.equals(idp.getPostBrokerLoginFlowId(), model.getId()));
}
public static boolean isClientScopeUsed(RealmModel realm, ClientScopeModel clientScope) {
@ -592,13 +582,14 @@ public final class KeycloakModelUtils {
}
public static ClientScopeModel getClientScopeByName(RealmModel realm, String clientScopeName) {
for (ClientScopeModel clientScope : realm.getClientScopes()) {
if (clientScopeName.equals(clientScope.getName())) {
return clientScope;
}
}
// check if we are referencing a client instead of a scope
return realm.getClientsStream().filter(c -> clientScopeName.equals(c.getClientId())).findFirst().orElse(null);
return realm.getClientScopesStream()
.filter(clientScope -> Objects.equals(clientScopeName, clientScope.getName()))
.findFirst()
// check if we are referencing a client instead of a scope
.orElse(realm.getClientsStream()
.filter(c -> Objects.equals(clientScopeName, c.getClientId()))
.findFirst()
.orElse(null));
}
/**

View file

@ -39,8 +39,6 @@ import org.keycloak.representations.idm.authorization.*;
import org.keycloak.storage.StorageId;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
@ -323,12 +321,10 @@ public class ModelToRepresentation {
if (realm.getEventsExpiration() != 0) {
rep.setEventsExpiration(realm.getEventsExpiration());
}
if (realm.getEventsListeners() != null) {
rep.setEventsListeners(new LinkedList<>(realm.getEventsListeners()));
}
if (realm.getEnabledEventTypes() != null) {
rep.setEnabledEventTypes(new LinkedList<>(realm.getEnabledEventTypes()));
}
rep.setEventsListeners(realm.getEventsListenersStream().collect(Collectors.toList()));
rep.setEnabledEventTypes(realm.getEnabledEventTypesStream().collect(Collectors.toList()));
rep.setAdminEventsEnabled(realm.isAdminEventsEnabled());
rep.setAdminEventsDetailsEnabled(realm.isAdminEventsDetailsEnabled());
@ -419,27 +415,23 @@ public class ModelToRepresentation {
rep.setDefaultGroups(defaultGroups);
}
List<RequiredCredentialModel> requiredCredentialModels = realm.getRequiredCredentials();
if (!requiredCredentialModels.isEmpty()) {
rep.setRequiredCredentials(new HashSet<>());
for (RequiredCredentialModel cred : requiredCredentialModels) {
rep.getRequiredCredentials().add(cred.getType());
}
Set<String> reqCredentials = realm.getRequiredCredentialsStream()
.map(RequiredCredentialModel::getType)
.collect(Collectors.toSet());
if (!reqCredentials.isEmpty()) {
rep.setRequiredCredentials(reqCredentials);
}
for (IdentityProviderModel provider : realm.getIdentityProviders()) {
rep.addIdentityProvider(toRepresentation(realm, provider));
}
List<IdentityProviderRepresentation> identityProviders = realm.getIdentityProvidersStream()
.map(provider -> toRepresentation(realm, provider)).collect(Collectors.toList());
rep.setIdentityProviders(identityProviders);
for (IdentityProviderMapperModel mapper : realm.getIdentityProviderMappers()) {
rep.addIdentityProviderMapper(toRepresentation(mapper));
}
List<IdentityProviderMapperRepresentation> identityProviderMappers = realm.getIdentityProviderMappersStream()
.map(ModelToRepresentation::toRepresentation).collect(Collectors.toList());
rep.setIdentityProviderMappers(identityProviderMappers);
rep.setInternationalizationEnabled(realm.isInternationalizationEnabled());
if (realm.getSupportedLocales() != null) {
rep.setSupportedLocales(new HashSet<>());
rep.getSupportedLocales().addAll(realm.getSupportedLocales());
}
rep.setSupportedLocales(realm.getSupportedLocalesStream().collect(Collectors.toSet()));
rep.setDefaultLocale(realm.getDefaultLocale());
if (internal) {
exportAuthenticationFlows(realm, rep);
@ -479,47 +471,22 @@ public class ModelToRepresentation {
}
public static void exportAuthenticationFlows(RealmModel realm, RealmRepresentation rep) {
rep.setAuthenticationFlows(new LinkedList<>());
rep.setAuthenticatorConfig(new LinkedList<>());
List<AuthenticationFlowModel> authenticationFlows = new ArrayList<>(realm.getAuthenticationFlows());
//ensure consistent ordering of authenticationFlows.
Collections.sort(authenticationFlows, new Comparator<AuthenticationFlowModel>() {
@Override
public int compare(AuthenticationFlowModel left, AuthenticationFlowModel right) {
String l = left.getAlias() != null ? left.getAlias() : "\0";
String r = right.getAlias() != null ? right.getAlias() : "\0";
return l.compareTo(r);
}
});
for (AuthenticationFlowModel model : authenticationFlows) {
AuthenticationFlowRepresentation flowRep = toRepresentation(realm, model);
rep.getAuthenticationFlows().add(flowRep);
}
List<AuthenticatorConfigModel> authenticatorConfigs = new ArrayList<>(realm.getAuthenticatorConfigs());
//ensure consistent ordering of authenticatorConfigs.
Collections.sort(authenticatorConfigs, new Comparator<AuthenticatorConfigModel>() {
@Override
public int compare(AuthenticatorConfigModel left, AuthenticatorConfigModel right) {
String l = left.getAlias() != null ? left.getAlias() : "\0";
String r = right.getAlias() != null ? right.getAlias() : "\0";
return l.compareTo(r);
}
});
for (AuthenticatorConfigModel model : authenticatorConfigs) {
rep.getAuthenticatorConfig().add(toRepresentation(model));
}
List<AuthenticationFlowRepresentation> authenticationFlows = realm.getAuthenticationFlowsStream()
.sorted(AuthenticationFlowModel.AuthenticationFlowComparator.SINGLETON)
.map(flow -> toRepresentation(realm, flow))
.collect(Collectors.toList());
rep.setAuthenticationFlows(authenticationFlows);
List<AuthenticatorConfigRepresentation> authenticationConfigs = realm.getAuthenticatorConfigsStream()
.sorted(AuthenticatorConfigModel.AuthenticationConfigComparator.SINGLETON)
.map(ModelToRepresentation::toRepresentation)
.collect(Collectors.toList());
rep.setAuthenticatorConfig(authenticationConfigs);
}
public static void exportRequiredActions(RealmModel realm, RealmRepresentation rep) {
rep.setRequiredActions(new LinkedList<>());
realm.getRequiredActionProviders().forEach(action -> rep.getRequiredActions().add(toRepresentation(action)));
rep.setRequiredActions(realm.getRequiredActionProvidersStream()
.map(ModelToRepresentation::toRepresentation).collect(Collectors.toList()));
}
public static RealmEventsConfigRepresentation toEventsConfigReprensetation(RealmModel realm) {
@ -530,13 +497,9 @@ public class ModelToRepresentation {
rep.setEventsExpiration(realm.getEventsExpiration());
}
if (realm.getEventsListeners() != null) {
rep.setEventsListeners(new LinkedList<>(realm.getEventsListeners()));
}
rep.setEventsListeners(realm.getEventsListenersStream().collect(Collectors.toList()));
if (realm.getEnabledEventTypes() != null) {
rep.setEnabledEventTypes(new LinkedList<>(realm.getEnabledEventTypes()));
}
rep.setEnabledEventTypes(realm.getEnabledEventTypesStream().collect(Collectors.toList()));
rep.setAdminEventsEnabled(realm.isAdminEventsEnabled());
@ -763,12 +726,9 @@ public class ModelToRepresentation {
rep.setProviderId(model.getProviderId());
rep.setAlias(model.getAlias());
rep.setDescription(model.getDescription());
rep.setAuthenticationExecutions(new LinkedList<>());
for (AuthenticationExecutionModel execution : realm.getAuthenticationExecutions(model.getId())) {
rep.getAuthenticationExecutions().add(toRepresentation(realm, execution));
}
rep.setAuthenticationExecutions(realm.getAuthenticationExecutionsStream(model.getId())
.map(e -> toRepresentation(realm, e)).collect(Collectors.toList()));
return rep;
}
public static AuthenticationExecutionExportRepresentation toRepresentation(RealmModel realm, AuthenticationExecutionModel model) {

View file

@ -446,7 +446,7 @@ public class RepresentationToModel {
}
}
if (newRealm.getComponents(newRealm.getId(), KeyProvider.class.getName()).isEmpty()) {
if (newRealm.getComponentsStream(newRealm.getId(), KeyProvider.class.getName()).count() == 0) {
if (rep.getPrivateKey() != null) {
DefaultKeyProviders.createProviders(newRealm, rep.getPrivateKey(), rep.getCertificate());
} else {

View file

@ -25,6 +25,7 @@ import org.keycloak.models.RealmModel;
import org.keycloak.provider.ProviderEvent;
import org.keycloak.provider.ProviderEventListener;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;
@ -76,12 +77,12 @@ public abstract class AbstractLoginProtocolFactory implements LoginProtocolFacto
}
protected void addDefaultClientScopes(RealmModel realm, Stream<ClientModel> newClients) {
Set<ClientScopeModel> defaultClientScopes = realm.getDefaultClientScopes(true).stream()
.filter(clientScope -> getId().equals(clientScope.getProtocol()))
Set<ClientScopeModel> defaultClientScopes = realm.getDefaultClientScopesStream(true)
.filter(clientScope -> Objects.equals(getId(), clientScope.getProtocol()))
.collect(Collectors.toSet());
Set<ClientScopeModel> nonDefaultClientScopes = realm.getDefaultClientScopes(false).stream()
.filter(clientScope -> getId().equals(clientScope.getProtocol()))
Set<ClientScopeModel> nonDefaultClientScopes = realm.getDefaultClientScopesStream(false)
.filter(clientScope -> Objects.equals(getId(), clientScope.getProtocol()))
.collect(Collectors.toSet());
Consumer<ClientModel> addDefault = c -> c.addClientScopes(defaultClientScopes, true);

View file

@ -17,8 +17,6 @@
package org.keycloak.utils;
import javax.ws.rs.core.Response;
import org.jboss.logging.Logger;
import org.keycloak.authentication.Authenticator;
import org.keycloak.authentication.AuthenticatorFactory;
@ -29,17 +27,16 @@ import org.keycloak.authentication.FormAction;
import org.keycloak.authentication.FormActionFactory;
import org.keycloak.credential.CredentialModel;
import org.keycloak.credential.CredentialProvider;
import org.keycloak.forms.account.AccountPages;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.AuthenticationFlowModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.credential.OTPCredentialModel;
import org.keycloak.models.utils.CredentialValidation;
import org.keycloak.representations.idm.CredentialRepresentation;
import java.util.Objects;
/**
* used to set an execution a state based on type.
*
@ -61,22 +58,25 @@ public class CredentialHelper {
}
public static void setOrReplaceAuthenticationRequirement(KeycloakSession session, RealmModel realm, String type, AuthenticationExecutionModel.Requirement requirement, AuthenticationExecutionModel.Requirement currentRequirement) {
for (AuthenticationFlowModel flow : realm.getAuthenticationFlows()) {
for (AuthenticationExecutionModel execution : realm.getAuthenticationExecutions(flow.getId())) {
String providerId = execution.getAuthenticator();
ConfigurableAuthenticatorFactory factory = getConfigurableAuthenticatorFactory(session, providerId);
if (factory == null) continue;
if (type.equals(factory.getReferenceCategory())) {
if (currentRequirement == null || currentRequirement.equals(execution.getRequirement())) {
execution.setRequirement(requirement);
realm.updateAuthenticatorExecution(execution);
logger.debugf("Authenticator execution '%s' switched to '%s'", execution.getAuthenticator(), requirement.toString());
} else {
logger.debugf("Skip switch authenticator execution '%s' to '%s' as it's in state %s", execution.getAuthenticator(), requirement.toString(), execution.getRequirement());
realm.getAuthenticationFlowsStream().forEach(flow -> realm.getAuthenticationExecutionsStream(flow.getId())
.filter(exe -> {
ConfigurableAuthenticatorFactory factory = getConfigurableAuthenticatorFactory(session, exe.getAuthenticator());
return Objects.nonNull(factory) && Objects.equals(type, factory.getReferenceCategory());
})
.filter(exe -> {
if (Objects.isNull(currentRequirement) || Objects.equals(exe.getRequirement(), currentRequirement))
return true;
else {
logger.debugf("Skip switch authenticator execution '%s' to '%s' as it's in state %s",
exe.getAuthenticator(), requirement.toString(), exe.getRequirement());
return false;
}
}
}
}
})
.forEachOrdered(exe -> {
exe.setRequirement(requirement);
realm.updateAuthenticatorExecution(exe);
logger.debugf("Authenticator execution '%s' switched to '%s'", exe.getAuthenticator(), requirement.toString());
}));
}
public static ConfigurableAuthenticatorFactory getConfigurableAuthenticatorFactory(KeycloakSession session, String providerId) {

View file

@ -17,11 +17,29 @@
package org.keycloak.utils;
import java.util.Iterator;
import java.util.Spliterators;
import java.util.function.Function;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
public class StreamsUtil {
public static <T> Stream<T> closing(Stream<T> stream) {
return Stream.of(stream).flatMap(Function.identity());
}
/**
* Returns the original stream if the stream is not empty. Otherwise throws the provided exception.
* @param stream Stream to be examined.
* @param ex Exception to be thrown if the stream is empty.
* @return Stream
*/
public static <T> Stream<T> throwIfEmpty(Stream<T> stream, RuntimeException ex) {
Iterator<T> iterator = stream.iterator();
if (iterator.hasNext()) {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false);
} else {
throw ex;
}
}
}

View file

@ -266,13 +266,10 @@ public class CredentialTypeMetadata implements Comparable<CredentialTypeMetadata
return false;
}
for (RequiredActionProviderModel requiredActionProvider : realm.getRequiredActionProviders()) {
if (requiredActionProviderId.equals(requiredActionProvider.getProviderId()) && requiredActionProvider.isEnabled()) {
return true;
}
}
return false;
return realm.getRequiredActionProvidersStream()
.filter(RequiredActionProviderModel::isEnabled)
.map(RequiredActionProviderModel::getProviderId)
.anyMatch(requiredActionProviderId::equals);
}
}

View file

@ -18,6 +18,7 @@
package org.keycloak.models;
import java.io.Serializable;
import java.util.Comparator;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -79,4 +80,17 @@ public class AuthenticationFlowModel implements Serializable {
public void setBuiltIn(boolean builtIn) {
this.builtIn = builtIn;
}
public static class AuthenticationFlowComparator implements Comparator<AuthenticationFlowModel> {
public static final AuthenticationFlowModel.AuthenticationFlowComparator SINGLETON =
new AuthenticationFlowModel.AuthenticationFlowComparator();
@Override
public int compare(AuthenticationFlowModel left, AuthenticationFlowModel right) {
//ensure consistent ordering of authenticationFlows.
String l = left.getAlias() != null ? left.getAlias() : "\0";
String r = right.getAlias() != null ? right.getAlias() : "\0";
return l.compareTo(r);
}
}
}

View file

@ -18,6 +18,7 @@
package org.keycloak.models;
import java.io.Serializable;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
@ -57,4 +58,17 @@ public class AuthenticatorConfigModel implements Serializable {
public void setConfig(Map<String, String> config) {
this.config = config;
}
public static class AuthenticationConfigComparator implements Comparator<AuthenticatorConfigModel> {
public static final AuthenticatorConfigModel.AuthenticationConfigComparator SINGLETON =
new AuthenticatorConfigModel.AuthenticationConfigComparator();
@Override
public int compare(AuthenticatorConfigModel left, AuthenticatorConfigModel right) {
//ensure consistent ordering of authenticationFlows.
String l = left.getAlias() != null ? left.getAlias() : "\0";
String r = right.getAlias() != null ? right.getAlias() : "\0";
return l.compareTo(r);
}
}
}

View file

@ -49,7 +49,7 @@ public interface GroupProvider extends Provider, GroupLookupProvider {
*
* @param realm Realm.
* @return List of groups in the Realm.
* @deprecated Use {@link #getGroupsStream(RealmModel)} getGroupsStream} instead.
* @deprecated Use {@link #getGroupsStream(RealmModel) getGroupsStream} instead.
*/
@Deprecated
default List<GroupModel> getGroups(RealmModel realm) {
@ -140,7 +140,7 @@ public interface GroupProvider extends Provider, GroupLookupProvider {
* @param firstResult First result to return. Ignored if negative.
* @param maxResults Maximum number of results to return. Ignored if negative.
* @return List of groups with the given role.
* @deprecated Use {@link #getGroupsByRoleStream(RealmModel, RoleModel, Integer, Integer)} getGroupsByRoleStream} instead.
* @deprecated Use {@link #getGroupsByRoleStream(RealmModel, RoleModel, int, int) getGroupsByRoleStream} instead.
*/
@Deprecated
default List<GroupModel> getGroupsByRole(RealmModel realm, RoleModel role, int firstResult, int maxResults) {
@ -163,7 +163,7 @@ public interface GroupProvider extends Provider, GroupLookupProvider {
*
* @param realm Realm.
* @return List of all top level groups in the realm.
* @deprecated Use {@link #getTopLevelGroupsStream(RealmModel)} getTopLevelGroupsStream} instead.
* @deprecated Use {@link #getTopLevelGroupsStream(RealmModel) getTopLevelGroupsStream} instead.
*/
@Deprecated
default List<GroupModel> getTopLevelGroups(RealmModel realm) {
@ -185,7 +185,7 @@ public interface GroupProvider extends Provider, GroupLookupProvider {
* @param firstResult First result to return. Ignored if negative or {@code null}.
* @param maxResults Maximum number of results to return. Ignored if negative or {@code null}.
* @return List of top level groups in the realm.
* @deprecated Use {@link #getTopLevelGroupsStream(RealmModel, Integer, Integer)} getTopLevelGroupsStream} instead.
* @deprecated Use {@link #getTopLevelGroupsStream(RealmModel, Integer, Integer) getTopLevelGroupsStream} instead.
*/
@Deprecated
default List<GroupModel> getTopLevelGroups(RealmModel realm, Integer firstResult, Integer maxResults) {

View file

@ -246,7 +246,15 @@ public interface RealmModel extends RoleContainerModel {
int getActionTokenGeneratedByUserLifespan(String actionTokenType);
void setActionTokenGeneratedByUserLifespan(String actionTokenType, Integer seconds);
List<RequiredCredentialModel> getRequiredCredentials();
/**
* @deprecated Use {@link #getRequiredCredentialsStream() getRequiredCredentialsStream} instead.
*/
@Deprecated
default List<RequiredCredentialModel> getRequiredCredentials() {
return getRequiredCredentialsStream().collect(Collectors.toList());
}
Stream<RequiredCredentialModel> getRequiredCredentialsStream();
void addRequiredCredential(String cred);
@ -360,42 +368,115 @@ public interface RealmModel extends RoleContainerModel {
AuthenticationFlowModel getDockerAuthenticationFlow();
void setDockerAuthenticationFlow(AuthenticationFlowModel flow);
List<AuthenticationFlowModel> getAuthenticationFlows();
/**
* @deprecated Use {@link #getAuthenticationFlowsStream() getAuthenticationFlowsStream} instead.
*/
@Deprecated
default List<AuthenticationFlowModel> getAuthenticationFlows() {
return getAuthenticationFlowsStream().collect(Collectors.toList());
}
Stream<AuthenticationFlowModel> getAuthenticationFlowsStream();
AuthenticationFlowModel getFlowByAlias(String alias);
AuthenticationFlowModel addAuthenticationFlow(AuthenticationFlowModel model);
AuthenticationFlowModel getAuthenticationFlowById(String id);
void removeAuthenticationFlow(AuthenticationFlowModel model);
void updateAuthenticationFlow(AuthenticationFlowModel model);
List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId);
/**
* @deprecated Use {@link #getAuthenticationExecutionsStream(String) getAuthenticationExecutionsStream} instead.
*/
@Deprecated
default List<AuthenticationExecutionModel> getAuthenticationExecutions(String flowId) {
return getAuthenticationExecutionsStream(flowId).collect(Collectors.toList());
}
/**
* Returns sorted {@link AuthenticationExecutionModel AuthenticationExecutionModel} as a stream.
* It should be used with forEachOrdered if the ordering is required.
* @return Sorted stream
*/
Stream<AuthenticationExecutionModel> getAuthenticationExecutionsStream(String flowId);
AuthenticationExecutionModel getAuthenticationExecutionById(String id);
AuthenticationExecutionModel getAuthenticationExecutionByFlowId(String flowId);
AuthenticationExecutionModel addAuthenticatorExecution(AuthenticationExecutionModel model);
void updateAuthenticatorExecution(AuthenticationExecutionModel model);
void removeAuthenticatorExecution(AuthenticationExecutionModel model);
/**
* @deprecated Use {@link #getAuthenticatorConfigsStream() getAuthenticatorConfigsStream} instead.
*/
@Deprecated
default List<AuthenticatorConfigModel> getAuthenticatorConfigs() {
return getAuthenticatorConfigsStream().collect(Collectors.toList());
}
Stream<AuthenticatorConfigModel> getAuthenticatorConfigsStream();
List<AuthenticatorConfigModel> getAuthenticatorConfigs();
AuthenticatorConfigModel addAuthenticatorConfig(AuthenticatorConfigModel model);
void updateAuthenticatorConfig(AuthenticatorConfigModel model);
void removeAuthenticatorConfig(AuthenticatorConfigModel model);
AuthenticatorConfigModel getAuthenticatorConfigById(String id);
AuthenticatorConfigModel getAuthenticatorConfigByAlias(String alias);
List<RequiredActionProviderModel> getRequiredActionProviders();
/**
* @deprecated Use {@link #getRequiredActionProvidersStream() getRequiredActionProvidersStream} instead.
*/
@Deprecated
default List<RequiredActionProviderModel> getRequiredActionProviders() {
return getRequiredActionProvidersStream().collect(Collectors.toList());
}
/**
* Returns sorted {@link RequiredActionProviderModel RequiredActionProviderModel} as a stream.
* It should be used with forEachOrdered if the ordering is required.
* @return Sorted stream
*/
Stream<RequiredActionProviderModel> getRequiredActionProvidersStream();
RequiredActionProviderModel addRequiredActionProvider(RequiredActionProviderModel model);
void updateRequiredActionProvider(RequiredActionProviderModel model);
void removeRequiredActionProvider(RequiredActionProviderModel model);
RequiredActionProviderModel getRequiredActionProviderById(String id);
RequiredActionProviderModel getRequiredActionProviderByAlias(String alias);
List<IdentityProviderModel> getIdentityProviders();
/**
* @deprecated Use {@link #getIdentityProvidersStream() getIdentityProvidersStream} instead.
*/
@Deprecated
default List<IdentityProviderModel> getIdentityProviders() {
return getIdentityProvidersStream().collect(Collectors.toList());
}
Stream<IdentityProviderModel> getIdentityProvidersStream();
IdentityProviderModel getIdentityProviderByAlias(String alias);
void addIdentityProvider(IdentityProviderModel identityProvider);
void removeIdentityProviderByAlias(String alias);
void updateIdentityProvider(IdentityProviderModel identityProvider);
Set<IdentityProviderMapperModel> getIdentityProviderMappers();
Set<IdentityProviderMapperModel> getIdentityProviderMappersByAlias(String brokerAlias);
/**
* @deprecated Use {@link #getIdentityProviderMappersStream() getIdentityProviderMappersStream} instead.
*/
@Deprecated
default Set<IdentityProviderMapperModel> getIdentityProviderMappers() {
return getIdentityProviderMappersStream().collect(Collectors.toSet());
}
Stream<IdentityProviderMapperModel> getIdentityProviderMappersStream();
/**
* @deprecated Use {@link #getIdentityProviderMappersByAliasStream(String) getIdentityProviderMappersByAliasStream} instead.
*/
@Deprecated
default Set<IdentityProviderMapperModel> getIdentityProviderMappersByAlias(String brokerAlias) {
return getIdentityProviderMappersByAliasStream(brokerAlias).collect(Collectors.toSet());
}
Stream<IdentityProviderMapperModel> getIdentityProviderMappersByAliasStream(String brokerAlias);
IdentityProviderMapperModel addIdentityProviderMapper(IdentityProviderMapperModel model);
void removeIdentityProviderMapper(IdentityProviderMapperModel mapping);
void updateIdentityProviderMapper(IdentityProviderMapperModel mapping);
@ -422,7 +503,15 @@ public interface RealmModel extends RoleContainerModel {
void updateComponent(ComponentModel component);
void removeComponent(ComponentModel component);
void removeComponents(String parentId);
List<ComponentModel> getComponents(String parentId, String providerType);
/**
* @deprecated Use {@link #getComponentsStream(String, String) getComponentsStream} instead.
*/
@Deprecated
default List<ComponentModel> getComponents(String parentId, String providerType) {
return getComponentsStream(parentId, providerType).collect(Collectors.toList());
}
/**
* Returns stream of ComponentModels for specific parentId and providerType.
@ -430,43 +519,85 @@ public interface RealmModel extends RoleContainerModel {
* @param providerType type of provider
* @return stream of ComponentModels
*/
default Stream<ComponentModel> getComponentsStream(String parentId, String providerType) {
return getComponents(parentId, providerType).stream();
Stream<ComponentModel> getComponentsStream(String parentId, String providerType);
Stream<ComponentModel> getComponentsStream(String parentId);
/**
* @deprecated Use {@link #getComponentsStream(String) getComponentsStream} instead.
*/
@Deprecated
default List<ComponentModel> getComponents(String parentId) {
return getComponentsStream(parentId).collect(Collectors.toList());
}
List<ComponentModel> getComponents(String parentId);
/**
* @deprecated Use {@link #getComponentsStream() getComponentsStream} instead.
*/
@Deprecated
default List<ComponentModel> getComponents() {
return getComponentsStream().collect(Collectors.toList());
}
Stream<ComponentModel> getComponentsStream();
List<ComponentModel> getComponents();
ComponentModel getComponent(String id);
default
List<UserStorageProviderModel> getUserStorageProviders() {
List<UserStorageProviderModel> list = new LinkedList<>();
for (ComponentModel component : getComponents(getId(), UserStorageProvider.class.getName())) {
list.add(new UserStorageProviderModel(component));
}
Collections.sort(list, UserStorageProviderModel.comparator);
return list;
/**
* @deprecated Use {@link #getUserStorageProvidersStream() getUserStorageProvidersStream} instead.
*/
@Deprecated
default List<UserStorageProviderModel> getUserStorageProviders() {
return getUserStorageProvidersStream().collect(Collectors.toList());
}
default
List<ClientStorageProviderModel> getClientStorageProviders() {
List<ClientStorageProviderModel> list = new LinkedList<>();
for (ComponentModel component : getComponents(getId(), ClientStorageProvider.class.getName())) {
list.add(new ClientStorageProviderModel(component));
}
Collections.sort(list, ClientStorageProviderModel.comparator);
return list;
/**
* Returns sorted {@link UserStorageProviderModel UserStorageProviderModel} as a stream.
* It should be used with forEachOrdered if the ordering is required.
* @return Sorted stream
*/
default Stream<UserStorageProviderModel> getUserStorageProvidersStream() {
return getComponentsStream(getId(), UserStorageProvider.class.getName())
.map(UserStorageProviderModel::new)
.sorted(UserStorageProviderModel.comparator);
}
default
List<RoleStorageProviderModel> getRoleStorageProviders() {
List<RoleStorageProviderModel> list = new LinkedList<>();
for (ComponentModel component : getComponents(getId(), RoleStorageProvider.class.getName())) {
list.add(new RoleStorageProviderModel(component));
}
Collections.sort(list, RoleStorageProviderModel.comparator);
return list;
/**
* @deprecated Use {@link #getClientStorageProvidersStream() getClientStorageProvidersStream} instead.
*/
@Deprecated
default List<ClientStorageProviderModel> getClientStorageProviders() {
return getClientStorageProvidersStream().collect(Collectors.toList());
}
/**
* Returns sorted {@link ClientStorageProviderModel ClientStorageProviderModel} as a stream.
* It should be used with forEachOrdered if the ordering is required.
* @return Sorted stream
*/
default Stream<ClientStorageProviderModel> getClientStorageProvidersStream() {
return getComponentsStream(getId(), ClientStorageProvider.class.getName())
.map(ClientStorageProviderModel::new)
.sorted(ClientStorageProviderModel.comparator);
}
/**
* @deprecated Use {@link #getRoleStorageProvidersStream() getRoleStorageProvidersStream} instead.
*/
@Deprecated
default List<RoleStorageProviderModel> getRoleStorageProviders() {
return getRoleStorageProvidersStream().collect(Collectors.toList());
}
/**
* Returns sorted {@link RoleStorageProviderModel RoleStorageProviderModel} as a stream.
* It should be used with forEachOrdered if the ordering is required.
* @return Sorted stream
*/
default Stream<RoleStorageProviderModel> getRoleStorageProvidersStream() {
return getComponentsStream(getId(), RoleStorageProvider.class.getName())
.map(RoleStorageProviderModel::new)
.sorted(RoleStorageProviderModel.comparator);
}
/**
@ -516,11 +647,27 @@ public interface RealmModel extends RoleContainerModel {
void setEventsExpiration(long expiration);
Set<String> getEventsListeners();
/**
* @deprecated Use {@link #getEventsListenersStream() getEventsListenersStream} instead.
*/
@Deprecated
default Set<String> getEventsListeners() {
return getEventsListenersStream().collect(Collectors.toSet());
}
Stream<String> getEventsListenersStream();
void setEventsListeners(Set<String> listeners);
Set<String> getEnabledEventTypes();
/**
* @deprecated Use {@link #getEnabledEventTypesStream() getEnabledEventTypesStream} instead.
*/
@Deprecated
default Set<String> getEnabledEventTypes() {
return getEnabledEventTypesStream().collect(Collectors.toSet());
}
Stream<String> getEnabledEventTypesStream();
void setEnabledEventTypes(Set<String> enabledEventTypes);
@ -540,7 +687,17 @@ public interface RealmModel extends RoleContainerModel {
boolean isInternationalizationEnabled();
void setInternationalizationEnabled(boolean enabled);
Set<String> getSupportedLocales();
/**
* @deprecated Use {@link #getSupportedLocalesStream() getSupportedLocalesStream} instead.
*/
@Deprecated
default Set<String> getSupportedLocales() {
return getSupportedLocalesStream().collect(Collectors.toSet());
}
Stream<String> getSupportedLocalesStream();
void setSupportedLocales(Set<String> locales);
String getDefaultLocale();
void setDefaultLocale(String locale);
@ -561,6 +718,9 @@ public interface RealmModel extends RoleContainerModel {
GroupModel getGroupById(String id);
/**
* @deprecated Use {@link #getGroupsStream() getGroupsStream} instead.
*/
@Deprecated
default List<GroupModel> getGroups() {
return getGroupsStream().collect(Collectors.toList());
@ -571,6 +731,9 @@ public interface RealmModel extends RoleContainerModel {
Long getGroupsCount(Boolean onlyTopGroups);
Long getGroupsCountByNameContaining(String search);
/**
* @deprecated Use {@link #getTopLevelGroups() getTopLevelGroups} instead.
*/
@Deprecated
default List<GroupModel> getTopLevelGroups() {
return getTopLevelGroupsStream().collect(Collectors.toList());
@ -578,6 +741,9 @@ public interface RealmModel extends RoleContainerModel {
Stream<GroupModel> getTopLevelGroupsStream();
/**
* @deprecated Use {@link #getTopLevelGroupsStream(Integer, Integer) getTopLevelGroupsStream} instead.
*/
@Deprecated
default List<GroupModel> getTopLevelGroups(Integer first, Integer max) {
return getTopLevelGroupsStream(first, max).collect(Collectors.toList());
@ -585,6 +751,9 @@ public interface RealmModel extends RoleContainerModel {
Stream<GroupModel> getTopLevelGroupsStream(Integer first, Integer max);
/**
* @deprecated Use {@link #searchForGroupByNameStream(String, Integer, Integer) searchForGroupByName} instead.
*/
@Deprecated
default List<GroupModel> searchForGroupByName(String search, Integer first, Integer max) {
return searchForGroupByNameStream(search, first, max).collect(Collectors.toList());
@ -595,7 +764,15 @@ public interface RealmModel extends RoleContainerModel {
boolean removeGroup(GroupModel group);
void moveGroup(GroupModel group, GroupModel toParent);
List<ClientScopeModel> getClientScopes();
/**
* @deprecated Use {@link #getClientScopesStream() getClientScopesStream} instead.
*/
@Deprecated
default List<ClientScopeModel> getClientScopes() {
return getClientScopesStream().collect(Collectors.toList());
}
Stream<ClientScopeModel> getClientScopesStream();
ClientScopeModel addClientScope(String name);
@ -607,6 +784,14 @@ public interface RealmModel extends RoleContainerModel {
void addDefaultClientScope(ClientScopeModel clientScope, boolean defaultScope);
void removeDefaultClientScope(ClientScopeModel clientScope);
List<ClientScopeModel> getDefaultClientScopes(boolean defaultScope);
/**
* @deprecated Use {@link #getDefaultClientScopesStream(boolean) getDefaultClientScopesStream} instead.
*/
@Deprecated
default List<ClientScopeModel> getDefaultClientScopes(boolean defaultScope) {
return getDefaultClientScopesStream(defaultScope).collect(Collectors.toList());
}
Stream<ClientScopeModel> getDefaultClientScopesStream(boolean defaultScope);
}

View file

@ -23,6 +23,7 @@ import org.keycloak.provider.Provider;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -39,14 +40,43 @@ public interface RealmProvider extends Provider /* TODO: Remove in future versio
ClientScopeModel getClientScopeById(String id, RealmModel realm);
List<RealmModel> getRealms();
List<RealmModel> getRealmsWithProviderType(Class<?> type);
/**
* @deprecated Use {@link #getRealmsStream() getRealmsStream} instead.
*/
@Deprecated
default List<RealmModel> getRealms() {
return getRealmsStream().collect(Collectors.toList());
}
Stream<RealmModel> getRealmsStream();
/**
* @deprecated Use {@link #getRealmsWithProviderTypeStream(Class)} getRealmsWithProviderTypeStream} instead.
*/
@Deprecated
default List<RealmModel> getRealmsWithProviderType(Class<?> type) {
return getRealmsWithProviderTypeStream(type).collect(Collectors.toList());
}
Stream<RealmModel> getRealmsWithProviderTypeStream(Class<?> type);
boolean removeRealm(String id);
ClientInitialAccessModel createClientInitialAccessModel(RealmModel realm, int expiration, int count);
ClientInitialAccessModel getClientInitialAccessModel(RealmModel realm, String id);
void removeClientInitialAccessModel(RealmModel realm, String id);
List<ClientInitialAccessModel> listClientInitialAccess(RealmModel realm);
/**
* @deprecated Use {@link #listClientInitialAccessStream(RealmModel)} listClientInitialAccessStream} instead.
*/
@Deprecated
default List<ClientInitialAccessModel> listClientInitialAccess(RealmModel realm) {
return listClientInitialAccessStream(realm).collect(Collectors.toList());
}
Stream<ClientInitialAccessModel> listClientInitialAccessStream(RealmModel realm);
void removeExpiredClientInitialAccess();
void decreaseRemainingCount(RealmModel realm, ClientInitialAccessModel clientInitialAccess); // Separate provider method to ensure we decrease remainingCount atomically instead of doing classic update

View file

@ -42,7 +42,7 @@ public interface GroupLookupProvider {
* @param firstResult First result to return. Ignored if {@code null}.
* @param maxResults Maximum number of results to return. Ignored if {@code null}.
* @return List of groups with the given string in name.
* @deprecated Use {@link #searchForGroupByNameStream(RealmModel, String, Integer, Integer)} searchForGroupByNameStream} instead.
* @deprecated Use {@link #searchForGroupByNameStream(RealmModel, String, Integer, Integer) searchForGroupByNameStream} instead.
*/
@Deprecated
default List<GroupModel> searchForGroupByName(RealmModel realm, String search, Integer firstResult, Integer maxResults) {

View file

@ -39,7 +39,6 @@ import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.utils.AuthenticationFlowResolver;
import org.keycloak.models.utils.FormMessage;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.protocol.LoginProtocol;
import org.keycloak.protocol.LoginProtocol.Error;
import org.keycloak.protocol.oidc.TokenManager;
@ -302,15 +301,15 @@ public class AuthenticationProcessor {
@Override
public AuthenticationExecutionModel.Requirement getCategoryRequirementFromCurrentFlow(String authenticatorCategory) {
List<AuthenticationExecutionModel> executions = realm.getAuthenticationExecutions(execution.getParentFlow());
for (AuthenticationExecutionModel exe : executions) {
AuthenticatorFactory factory = (AuthenticatorFactory) getSession().getKeycloakSessionFactory().getProviderFactory(Authenticator.class, exe.getAuthenticator());
if (factory != null && factory.getReferenceCategory().equals(authenticatorCategory)) {
return exe.getRequirement();
}
}
return null;
return realm.getAuthenticationExecutionsStream(execution.getParentFlow())
.filter(e -> {
AuthenticatorFactory factory = (AuthenticatorFactory) getSession().getKeycloakSessionFactory()
.getProviderFactory(Authenticator.class, e.getAuthenticator());
return factory != null && factory.getReferenceCategory().equals(authenticatorCategory);
})
.map(AuthenticationExecutionModel::getRequirement)
.findFirst()
.orElse(null);
}
@Override
@ -1045,7 +1044,7 @@ public class AuthenticationProcessor {
}
public void evaluateRequiredActionTriggers() {
AuthenticationManager.evaluateRequiredActionTriggers(session, authenticationSession, connection, request, uriInfo, event, realm, authenticationSession.getAuthenticatedUser());
AuthenticationManager.evaluateRequiredActionTriggers(session, authenticationSession, request, event, realm, authenticationSession.getAuthenticatedUser());
}
public Response finishAuthentication(LoginProtocol protocol) {
@ -1076,7 +1075,7 @@ public class AuthenticationProcessor {
}
public String nextRequiredAction() {
return AuthenticationManager.nextRequiredAction(session, authenticationSession, connection, request, uriInfo, event);
return AuthenticationManager.nextRequiredAction(session, authenticationSession, request, event);
}
public AuthenticationProcessor.Result createAuthenticatorContext(AuthenticationExecutionModel model, Authenticator authenticator, List<AuthenticationExecutionModel> executions) {

View file

@ -24,10 +24,6 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import org.jboss.logging.Logger;
import org.keycloak.credential.CredentialModel;
import org.keycloak.models.AuthenticationExecutionModel;
@ -136,7 +132,8 @@ class AuthenticationSelectionResolver {
}
// Find the corresponding execution. If it is 1st REQUIRED execution in the particular subflow, we need to consider parent flow as well
List<AuthenticationExecutionModel> executions = realm.getAuthenticationExecutions(execution.getParentFlow());
List<AuthenticationExecutionModel> executions = realm.getAuthenticationExecutionsStream(execution.getParentFlow())
.collect(Collectors.toList());
int executionIndex = executions.indexOf(execution);
if (executionIndex != 0) {
return flowId;
@ -188,11 +185,9 @@ class AuthenticationSelectionResolver {
logger.debugf("Going through the flow '%s' for adding executions", flowModel.getAlias());
List<AuthenticationExecutionModel> executions = processor.getRealm().getAuthenticationExecutions(flowId);
List<AuthenticationExecutionModel> requiredList = new ArrayList<>();
List<AuthenticationExecutionModel> alternativeList = new ArrayList<>();
flow.fillListsOfExecutions(executions, requiredList, alternativeList);
flow.fillListsOfExecutions(processor.getRealm().getAuthenticationExecutionsStream(flowId), requiredList, alternativeList);
// If requiredList is not empty, we're going to collect just very first execution from the flow
if (!requiredList.isEmpty()) {

View file

@ -1,78 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.authentication;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.RealmModel;
import java.util.LinkedList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class AuthenticatorUtil {
public static List<AuthenticationExecutionModel> getEnabledExecutionsRecursively(RealmModel realm, String flowId) {
List<AuthenticationExecutionModel> executions = new LinkedList<>();
recurseExecutions(realm, flowId, executions);
return executions;
}
public static void recurseExecutions(RealmModel realm, String flowId, List<AuthenticationExecutionModel> executions) {
List<AuthenticationExecutionModel> authenticationExecutions = realm.getAuthenticationExecutions(flowId);
if (authenticationExecutions == null) return;
for (AuthenticationExecutionModel model : authenticationExecutions) {
executions.add(model);
if (model.isAuthenticatorFlow() && model.isEnabled()) {
recurseExecutions(realm, model.getFlowId(), executions);
}
}
}
public static AuthenticationExecutionModel findExecutionByAuthenticator(RealmModel realm, String flowId, String authProviderId) {
for (AuthenticationExecutionModel model : realm.getAuthenticationExecutions(flowId)) {
if (model.isAuthenticatorFlow()) {
AuthenticationExecutionModel recurse = findExecutionByAuthenticator(realm, model.getFlowId(), authProviderId);
if (recurse != null) return recurse;
}
if (model.getAuthenticator().equals(authProviderId)) {
return model;
}
}
return null;
}
public static boolean isEnabled(RealmModel realm, String flowId, String authProviderId) {
AuthenticationExecutionModel execution = findExecutionByAuthenticator(realm, flowId, authProviderId);
if (execution == null) {
return false;
}
return execution.isEnabled();
}
public static boolean isRequired(RealmModel realm, String flowId, String authProviderId) {
AuthenticationExecutionModel execution = findExecutionByAuthenticator(realm, flowId, authProviderId);
if (execution == null) {
return false;
}
return execution.isRequired();
}
}

View file

@ -29,7 +29,9 @@ import org.keycloak.services.ServicesLogger;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@ -106,19 +108,23 @@ public class ClientAuthenticationFlow implements AuthenticationFlow {
}
protected List<AuthenticationExecutionModel> findExecutionsToRun() {
List<AuthenticationExecutionModel> executions = processor.getRealm().getAuthenticationExecutions(flow.getId());
List<AuthenticationExecutionModel> executionsToRun = new ArrayList<>();
List<AuthenticationExecutionModel> executionsToRun = new LinkedList<>();
List<AuthenticationExecutionModel> finalExecutionsToRun = executionsToRun;
Optional<AuthenticationExecutionModel> first = processor.getRealm().getAuthenticationExecutionsStream(flow.getId())
.filter(e -> {
if (e.isRequired()) {
return true;
} else if (e.isAlternative()){
finalExecutionsToRun.add(e);
return false;
}
return false;
}).findFirst();
for (AuthenticationExecutionModel execution : executions) {
if (execution.isRequired()) {
executionsToRun = Arrays.asList(execution);
break;
}
if (execution.isAlternative()) {
executionsToRun.add(execution);
}
}
if (first.isPresent())
executionsToRun = Arrays.asList(first.get());
else
executionsToRun.addAll(finalExecutionsToRun);
if (logger.isTraceEnabled()) {
List<String> exIds = new ArrayList<>();

View file

@ -23,7 +23,6 @@ import org.keycloak.authentication.authenticators.conditional.ConditionalAuthent
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.AuthenticationFlowModel;
import org.keycloak.models.Constants;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.services.ServicesLogger;
import org.keycloak.sessions.AuthenticationSessionModel;
@ -35,7 +34,9 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -52,7 +53,7 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
public DefaultAuthenticationFlow(AuthenticationProcessor processor, AuthenticationFlowModel flow) {
this.processor = processor;
this.flow = flow;
this.executions = processor.getRealm().getAuthenticationExecutions(flow.getId());
this.executions = processor.getRealm().getAuthenticationExecutionsStream(flow.getId()).collect(Collectors.toList());
}
protected boolean isProcessed(AuthenticationExecutionModel model) {
@ -204,13 +205,13 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
*/
private String checkAndValidateParentFlow(AuthenticationExecutionModel model) {
while (true) {
List<AuthenticationExecutionModel> localExecutions = processor.getRealm().getAuthenticationExecutions(model.getParentFlow());
AuthenticationExecutionModel parentFlowExecutionModel = processor.getRealm().getAuthenticationExecutionByFlowId(model.getParentFlow());
if (parentFlowExecutionModel != null) {
List<AuthenticationExecutionModel> requiredExecutions = new LinkedList<>();
List<AuthenticationExecutionModel> alternativeExecutions = new LinkedList<>();
fillListsOfExecutions(localExecutions, requiredExecutions, alternativeExecutions);
fillListsOfExecutions(processor.getRealm().getAuthenticationExecutionsStream(model.getParentFlow()),
requiredExecutions, alternativeExecutions);
// Note: If we evaluate alternative execution, we will also doublecheck that there are not required elements in same subflow
if ((model.isRequired() && requiredExecutions.stream().allMatch(processor::isSuccessful)) ||
@ -237,7 +238,7 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
List<AuthenticationExecutionModel> requiredList = new ArrayList<>();
List<AuthenticationExecutionModel> alternativeList = new ArrayList<>();
fillListsOfExecutions(executions, requiredList, alternativeList);
fillListsOfExecutions(executions.stream(), requiredList, alternativeList);
//handle required elements : all required elements need to be executed
boolean requiredElementsSuccessful = true;
@ -296,16 +297,16 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
/**
* Just iterates over executionsToProcess and fill "requiredList" and "alternativeList" according to it
*/
void fillListsOfExecutions(List<AuthenticationExecutionModel> executionsToProcess, List<AuthenticationExecutionModel> requiredList, List<AuthenticationExecutionModel> alternativeList) {
for (AuthenticationExecutionModel execution : executionsToProcess) {
if (isConditionalAuthenticator(execution)) {
continue;
} else if (execution.isRequired() || execution.isConditional()) {
requiredList.add(execution);
} else if (execution.isAlternative()) {
alternativeList.add(execution);
}
}
void fillListsOfExecutions(Stream<AuthenticationExecutionModel> executionsToProcess, List<AuthenticationExecutionModel> requiredList, List<AuthenticationExecutionModel> alternativeList) {
executionsToProcess
.filter(((Predicate<AuthenticationExecutionModel>) this::isConditionalAuthenticator).negate())
.forEachOrdered(execution -> {
if (execution.isRequired() || execution.isConditional()) {
requiredList.add(execution);
} else if (execution.isAlternative()) {
alternativeList.add(execution);
}
});
if (!requiredList.isEmpty() && !alternativeList.isEmpty()) {
List<String> alternativeIds = alternativeList.stream()
@ -327,12 +328,14 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
if (model == null || !model.isAuthenticatorFlow() || !model.isConditional()) {
return false;
};
List<AuthenticationExecutionModel> modelList = processor.getRealm().getAuthenticationExecutions(model.getFlowId());
List<AuthenticationExecutionModel> modelList = processor.getRealm()
.getAuthenticationExecutionsStream(model.getFlowId()).collect(Collectors.toList());
List<AuthenticationExecutionModel> conditionalAuthenticatorList = modelList.stream()
.filter(this::isConditionalAuthenticator)
.filter(s -> s.isEnabled())
.collect(Collectors.toList());
return conditionalAuthenticatorList.isEmpty() || conditionalAuthenticatorList.stream().anyMatch(m-> conditionalNotMatched(m, modelList));
return conditionalAuthenticatorList.isEmpty() || conditionalAuthenticatorList.stream()
.anyMatch(m -> conditionalNotMatched(m, modelList));
}
private boolean isConditionalAuthenticator(AuthenticationExecutionModel model) {

View file

@ -42,6 +42,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -57,7 +58,7 @@ public class FormAuthenticationFlow implements AuthenticationFlow {
public FormAuthenticationFlow(AuthenticationProcessor processor, AuthenticationExecutionModel execution) {
this.processor = processor;
this.formExecution = execution;
formActionExecutions = processor.getRealm().getAuthenticationExecutions(execution.getFlowId());
formActionExecutions = processor.getRealm().getAuthenticationExecutionsStream(execution.getFlowId()).collect(Collectors.toList());
formAuthenticator = processor.getSession().getProvider(FormAuthenticator.class, execution.getAuthenticator());
}

View file

@ -103,7 +103,7 @@ public class ExecuteActionsActionTokenHandler extends AbstractActionTokenHander<
// verify user email as we know it is valid as this entry point would never have gotten here.
user.setEmailVerified(true);
String nextAction = AuthenticationManager.nextRequiredAction(tokenContext.getSession(), authSession, tokenContext.getClientConnection(), tokenContext.getRequest(), tokenContext.getUriInfo(), tokenContext.getEvent());
String nextAction = AuthenticationManager.nextRequiredAction(tokenContext.getSession(), authSession, tokenContext.getRequest(), tokenContext.getEvent());
return AuthenticationManager.redirectToRequiredActions(tokenContext.getSession(), tokenContext.getRealm(), authSession, tokenContext.getUriInfo(), nextAction);
}

View file

@ -111,7 +111,7 @@ public class VerifyEmailActionTokenHandler extends AbstractActionTokenHander<Ver
tokenContext.setEvent(event.clone().removeDetail(Details.EMAIL).event(EventType.LOGIN));
String nextAction = AuthenticationManager.nextRequiredAction(session, authSession, tokenContext.getClientConnection(), tokenContext.getRequest(), uriInfo, event);
String nextAction = AuthenticationManager.nextRequiredAction(session, authSession, tokenContext.getRequest(), event);
return AuthenticationManager.redirectToRequiredActions(session, realm, authSession, uriInfo, nextAction);
}

View file

@ -18,7 +18,6 @@
package org.keycloak.authentication.authenticators.browser;
import org.keycloak.authentication.AuthenticationFlowContext;
import org.keycloak.models.AuthenticatorConfigModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
@ -287,8 +286,7 @@ public class ConditionalOtpFormAuthenticator extends OTPFormAuthenticator {
private boolean isOTPRequired(KeycloakSession session, RealmModel realm, UserModel user) {
MultivaluedMap<String, String> requestHeaders = session.getContext().getRequestHeaders().getRequestHeaders();
for (AuthenticatorConfigModel configModel : realm.getAuthenticatorConfigs()) {
return realm.getAuthenticatorConfigsStream().anyMatch(configModel -> {
if (tryConcludeBasedOn(voteForUserOtpControlAttribute(user, configModel.getConfig()))) {
return true;
}
@ -311,8 +309,8 @@ public class ConditionalOtpFormAuthenticator extends OTPFormAuthenticator {
|| voteForDefaultFallback(configModel.getConfig()) == ABSTAIN)) {
return true;
}
}
return false;
return false;
});
}
private boolean containsConditionalOtpConfig(Map config) {

View file

@ -34,7 +34,8 @@ import org.keycloak.services.managers.ClientSessionCode;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import java.net.URI;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -67,27 +68,28 @@ public class IdentityProviderAuthenticator implements Authenticator {
}
private void redirect(AuthenticationFlowContext context, String providerId) {
List<IdentityProviderModel> identityProviders = context.getRealm().getIdentityProviders();
for (IdentityProviderModel identityProvider : identityProviders) {
if (identityProvider.isEnabled() && providerId.equals(identityProvider.getAlias())) {
String accessCode = new ClientSessionCode<>(context.getSession(), context.getRealm(), context.getAuthenticationSession()).getOrGenerateCode();
String clientId = context.getAuthenticationSession().getClient().getClientId();
String tabId = context.getAuthenticationSession().getTabId();
URI location = Urls.identityProviderAuthnRequest(context.getUriInfo().getBaseUri(), providerId, context.getRealm().getName(), accessCode, clientId, tabId);
if (context.getAuthenticationSession().getClientNote(OAuth2Constants.DISPLAY) != null) {
location = UriBuilder.fromUri(location).queryParam(OAuth2Constants.DISPLAY, context.getAuthenticationSession().getClientNote(OAuth2Constants.DISPLAY)).build();
}
Response response = Response.seeOther(location)
.build();
// will forward the request to the IDP with prompt=none if the IDP accepts forwards with prompt=none.
if ("none".equals(context.getAuthenticationSession().getClientNote(OIDCLoginProtocol.PROMPT_PARAM)) &&
Boolean.valueOf(identityProvider.getConfig().get(ACCEPTS_PROMPT_NONE))) {
context.getAuthenticationSession().setAuthNote(AuthenticationProcessor.FORWARDED_PASSIVE_LOGIN, "true");
}
LOG.debugf("Redirecting to %s", providerId);
context.forceChallenge(response);
return;
Optional<IdentityProviderModel> idp = context.getRealm().getIdentityProvidersStream()
.filter(IdentityProviderModel::isEnabled)
.filter(identityProvider -> Objects.equals(providerId, identityProvider.getAlias()))
.findFirst();
if (idp.isPresent()) {
String accessCode = new ClientSessionCode<>(context.getSession(), context.getRealm(), context.getAuthenticationSession()).getOrGenerateCode();
String clientId = context.getAuthenticationSession().getClient().getClientId();
String tabId = context.getAuthenticationSession().getTabId();
URI location = Urls.identityProviderAuthnRequest(context.getUriInfo().getBaseUri(), providerId, context.getRealm().getName(), accessCode, clientId, tabId);
if (context.getAuthenticationSession().getClientNote(OAuth2Constants.DISPLAY) != null) {
location = UriBuilder.fromUri(location).queryParam(OAuth2Constants.DISPLAY, context.getAuthenticationSession().getClientNote(OAuth2Constants.DISPLAY)).build();
}
Response response = Response.seeOther(location)
.build();
// will forward the request to the IDP with prompt=none if the IDP accepts forwards with prompt=none.
if ("none".equals(context.getAuthenticationSession().getClientNote(OIDCLoginProtocol.PROMPT_PARAM)) &&
Boolean.valueOf(idp.get().getConfig().get(ACCEPTS_PROMPT_NONE))) {
context.getAuthenticationSession().setAuthNote(AuthenticationProcessor.FORWARDED_PASSIVE_LOGIN, "true");
}
LOG.debugf("Redirecting to %s", providerId);
context.forceChallenge(response);
return;
}
LOG.warnf("Provider not found or not enabled for realm %s", providerId);

View file

@ -1,7 +1,8 @@
package org.keycloak.authentication.authenticators.conditional;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import org.keycloak.authentication.AuthenticationFlowContext;
import org.keycloak.authentication.Authenticator;
@ -20,34 +21,19 @@ public class ConditionalUserConfiguredAuthenticator implements ConditionalAuthen
}
private boolean matchConditionInFlow(AuthenticationFlowContext context, String flowId) {
List<AuthenticationExecutionModel> executions = context.getRealm().getAuthenticationExecutions(flowId);
if (executions==null) {
return true;
}
List<AuthenticationExecutionModel> requiredExecutions = new ArrayList<>();
List<AuthenticationExecutionModel> alternativeExecutions = new ArrayList<>();
executions.forEach(e -> {
//Check if the execution's authenticator is a conditional authenticator, as they must not be evaluated here.
boolean isConditionalAuthenticator = false;
try {
AuthenticatorFactory factory = (AuthenticatorFactory) context.getSession().getKeycloakSessionFactory().getProviderFactory(Authenticator.class, e.getAuthenticator());
if (factory != null) {
Authenticator auth = factory.create(context.getSession());
if (auth instanceof ConditionalAuthenticator) {
isConditionalAuthenticator = true;
List<AuthenticationExecutionModel> requiredExecutions = new LinkedList<>();
List<AuthenticationExecutionModel> alternativeExecutions = new LinkedList<>();
context.getRealm().getAuthenticationExecutionsStream(flowId)
//Check if the execution's authenticator is a conditional authenticator, as they must not be evaluated here.
.filter(e -> isConditionalExecution(context, e))
.filter(e -> !Objects.equals(context.getExecution().getId(), e.getId()) && !e.isAuthenticatorFlow())
.forEachOrdered(e -> {
if (e.isRequired()) {
requiredExecutions.add(e);
} else if (e.isAlternative()) {
alternativeExecutions.add(e);
}
}
} catch (Exception exception) {
//don't need to catch this
}
if (!context.getExecution().getId().equals(e.getId()) && !e.isAuthenticatorFlow() && !isConditionalAuthenticator) {
if (e.isRequired()) {
requiredExecutions.add(e);
} else if (e.isAlternative()) {
alternativeExecutions.add(e);
}
}
});
});
if (!requiredExecutions.isEmpty()) {
return requiredExecutions.stream().allMatch(e -> isConfiguredFor(e, context));
} else if (!alternativeExecutions.isEmpty()) {
@ -56,6 +42,18 @@ public class ConditionalUserConfiguredAuthenticator implements ConditionalAuthen
return true;
}
private boolean isConditionalExecution(AuthenticationFlowContext context, AuthenticationExecutionModel e) {
AuthenticatorFactory factory = (AuthenticatorFactory) context.getSession().getKeycloakSessionFactory()
.getProviderFactory(Authenticator.class, e.getAuthenticator());
if (factory != null) {
Authenticator auth = factory.create(context.getSession());
if (auth instanceof ConditionalAuthenticator) {
return false;
}
}
return true;
}
private boolean isConfiguredFor(AuthenticationExecutionModel model, AuthenticationFlowContext context) {
if (model.isAuthenticatorFlow()) {
return matchConditionInFlow(context, model.getId());

View file

@ -25,7 +25,6 @@ import org.keycloak.models.UserModel;
import org.keycloak.models.cache.CachedUserModel;
import org.keycloak.models.cache.OnUserCache;
import org.keycloak.models.cache.UserCache;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.storage.StorageId;
import org.keycloak.storage.UserStorageManager;
import org.keycloak.storage.UserStorageProvider;
@ -36,8 +35,10 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -172,11 +173,9 @@ public class UserCredentialStoreManager implements UserCredentialManager, OnUser
if (toValidate.isEmpty()) return true;
List<CredentialInputValidator> credentialProviders = getCredentialProviders(session, realm, CredentialInputValidator.class);
for (CredentialInputValidator validator : credentialProviders) {
validate(realm, user, toValidate, validator);
getCredentialProviders(session, CredentialInputValidator.class)
.forEach(validator -> validate(realm, user, toValidate, validator));
}
return toValidate.isEmpty();
}
@ -190,14 +189,11 @@ public class UserCredentialStoreManager implements UserCredentialManager, OnUser
}
}
public static <T> List<T> getCredentialProviders(KeycloakSession session, RealmModel realm, Class<T> type) {
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()));
}
return list;
public static <T> Stream<T> getCredentialProviders(KeycloakSession session, Class<T> type) {
return session.getKeycloakSessionFactory().getProviderFactories(CredentialProvider.class)
.stream()
.filter(f -> Types.supports(type, f, CredentialProviderFactory.class))
.map(f -> (T) session.getProvider(CredentialProvider.class, f.getId()));
}
@Override
@ -224,14 +220,9 @@ public class UserCredentialStoreManager implements UserCredentialManager, OnUser
}
}
List<CredentialInputUpdater> credentialProviders = getCredentialProviders(session, realm, CredentialInputUpdater.class);
for (CredentialInputUpdater updater : credentialProviders) {
if (!updater.supportsCredentialType(input.getType())) continue;
if (updater.updateCredential(realm, user, input)) return true;
}
return false;
return getCredentialProviders(session, CredentialInputUpdater.class)
.filter(updater -> updater.supportsCredentialType(input.getType()))
.anyMatch(updater -> updater.updateCredential(realm, user, input));
}
@Override
@ -259,14 +250,9 @@ public class UserCredentialStoreManager implements UserCredentialManager, OnUser
}
List<CredentialInputUpdater> credentialProviders = getCredentialProviders(session, realm, CredentialInputUpdater.class);
for (CredentialInputUpdater updater : credentialProviders) {
if (!updater.supportsCredentialType(credentialType)) continue;
updater.disableCredentialType(realm, user, credentialType);
}
getCredentialProviders(session, CredentialInputUpdater.class)
.filter(updater -> updater.supportsCredentialType(credentialType))
.forEach(updater -> updater.disableCredentialType(realm, user, credentialType));
}
@Override
@ -291,10 +277,11 @@ public class UserCredentialStoreManager implements UserCredentialManager, OnUser
}
List<CredentialInputUpdater> credentialProviders = getCredentialProviders(session, realm, CredentialInputUpdater.class);
for (CredentialInputUpdater updater : credentialProviders) {
types.addAll(updater.getDisableableCredentialTypes(realm, user));
}
types.addAll(getCredentialProviders(session, CredentialInputUpdater.class)
.map(updater -> updater.getDisableableCredentialTypes(realm, user))
.flatMap(Set::stream)
.collect(Collectors.toSet()));
return types;
}
@ -347,50 +334,38 @@ public class UserCredentialStoreManager implements UserCredentialManager, OnUser
@Override
public boolean isConfiguredLocally(RealmModel realm, UserModel user, String type) {
List<CredentialInputValidator> credentialProviders = getCredentialProviders(session, realm, CredentialInputValidator.class);
for (CredentialInputValidator validator : credentialProviders) {
if (validator.supportsCredentialType(type) && validator.isConfiguredFor(realm, user, type)) {
return true;
}
}
return false;
return getCredentialProviders(session, CredentialInputValidator.class)
.anyMatch(validator -> validator.supportsCredentialType(type) && validator.isConfiguredFor(realm, user, type));
}
@Override
public CredentialValidationOutput authenticate(KeycloakSession session, RealmModel realm, CredentialInput input) {
List<CredentialAuthentication> list = UserStorageManager.getEnabledStorageProviders(session, realm, CredentialAuthentication.class);
for (CredentialAuthentication auth : list) {
if (auth.supportsCredentialAuthenticationFor(input.getType())) {
CredentialValidationOutput output = auth.authenticate(realm, input);
if (output != null) return output;
}
}
CredentialValidationOutput output = authenticate(
UserStorageManager.getEnabledStorageProviders(session, realm, CredentialAuthentication.class),
realm, input);
list = getCredentialProviders(session, realm, CredentialAuthentication.class);
for (CredentialAuthentication auth : list) {
if (auth.supportsCredentialAuthenticationFor(input.getType())) {
CredentialValidationOutput output = auth.authenticate(realm, input);
if (output != null) return output;
}
}
return (output != null) ? output : authenticate(getCredentialProviders(session, CredentialAuthentication.class),
realm, input);
}
return null;
public CredentialValidationOutput authenticate(Stream<CredentialAuthentication> storageProviders,
RealmModel realm, CredentialInput input) {
return storageProviders
.filter(auth -> auth.supportsCredentialAuthenticationFor(input.getType()))
.map(auth -> auth.authenticate(realm, input))
.filter(Objects::nonNull)
.findFirst()
.orElse(null);
}
@Override
public void onCache(RealmModel realm, CachedUserModel user, UserModel delegate) {
List<OnUserCache> credentialProviders = getCredentialProviders(session, realm, OnUserCache.class);
for (OnUserCache validator : credentialProviders) {
validator.onCache(realm, user, delegate);
}
getCredentialProviders(session, OnUserCache.class).forEach(validator -> validator.onCache(realm, user, delegate));
}
@Override
public List<String> getConfiguredUserStorageCredentialTypes(RealmModel realm, UserModel user) {
List<CredentialProvider> credentialProviders = getCredentialProviders(session, realm, CredentialProvider.class);
return credentialProviders.stream().map(CredentialProvider::getType)
return getCredentialProviders(session, CredentialProvider.class).map(CredentialProvider::getType)
.filter(credentialType -> UserStorageCredentialConfigured.CONFIGURED == isConfiguredThroughUserStorage(realm, user, credentialType))
.collect(Collectors.toList());
}

View file

@ -18,6 +18,7 @@
package org.keycloak.exportimport.singlefile;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.jboss.logging.Logger;
import org.keycloak.exportimport.ExportProvider;
import org.keycloak.exportimport.util.ExportImportSessionTask;
@ -27,13 +28,12 @@ import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.util.JsonSerialization;
import org.keycloak.services.util.ObjectMapperResolver;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@ -59,15 +59,11 @@ public class SingleFileExportProvider implements ExportProvider {
@Override
protected void runExportImportTask(KeycloakSession session) throws IOException {
List<RealmModel> realms = session.realms().getRealms();
List<RealmRepresentation> reps = new ArrayList<>();
for (RealmModel realm : realms) {
reps.add(ExportUtils.exportRealm(session, realm, true, true));
}
Stream<RealmRepresentation> realms = session.realms().getRealmsStream()
.map(realm -> ExportUtils.exportRealm(session, realm, true, true));
writeToFile(reps);
writeToFile(realms);
}
});
}
@ -92,7 +88,10 @@ public class SingleFileExportProvider implements ExportProvider {
}
private ObjectMapper getObjectMapper() {
return JsonSerialization.prettyMapper;
ObjectMapper streamSerializer = ObjectMapperResolver.createStreamSerializer();
streamSerializer.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
streamSerializer.enable(SerializationFeature.INDENT_OUTPUT);
return streamSerializer;
}
private void writeToFile(Object reps) throws IOException {

View file

@ -43,7 +43,6 @@ import org.keycloak.authorization.store.PolicyStore;
import org.keycloak.authorization.store.StoreFactory;
import org.keycloak.common.Version;
import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.component.ComponentModel;
import org.keycloak.credential.CredentialModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientScopeModel;
@ -56,7 +55,6 @@ import org.keycloak.models.UserConsentModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.ModelToRepresentation;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.ClientScopeRepresentation;
import org.keycloak.representations.idm.ComponentExportRepresentation;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.FederatedIdentityRepresentation;
@ -98,23 +96,11 @@ public class ExportUtils {
rep.setKeycloakVersion(Version.VERSION_KEYCLOAK);
// Client Scopes
List<ClientScopeModel> clientScopeModels = realm.getClientScopes();
List<ClientScopeRepresentation> clientScopesReps = new ArrayList<>();
for (ClientScopeModel app : clientScopeModels) {
ClientScopeRepresentation clientRep = ModelToRepresentation.toRepresentation(app);
clientScopesReps.add(clientRep);
}
rep.setClientScopes(clientScopesReps);
List<String> defaultClientScopeNames = realm.getDefaultClientScopes(true).stream().map((ClientScopeModel clientScope) -> {
return clientScope.getName();
}).collect(Collectors.toList());
rep.setDefaultDefaultClientScopes(defaultClientScopeNames);
List<String> optionalClientScopeNames = realm.getDefaultClientScopes(false).stream().map((ClientScopeModel clientScope) -> {
return clientScope.getName();
}).collect(Collectors.toList());
rep.setDefaultOptionalClientScopes(optionalClientScopeNames);
rep.setClientScopes(realm.getClientScopesStream().map(ModelToRepresentation::toRepresentation).collect(Collectors.toList()));
rep.setDefaultDefaultClientScopes(realm.getDefaultClientScopesStream(true)
.map(ClientScopeModel::getName).collect(Collectors.toList()));
rep.setDefaultOptionalClientScopes(realm.getDefaultClientScopesStream(false)
.map(ClientScopeModel::getName).collect(Collectors.toList()));
// Clients
List<ClientModel> clients = Collections.emptyList();
@ -199,7 +185,7 @@ public class ExportUtils {
}
// Scopes of client scopes
for (ClientScopeModel clientScope : realm.getClientScopes()) {
realm.getClientScopesStream().forEach(clientScope -> {
Set<RoleModel> clientScopes = clientScope.getScopeMappingsStream().collect(Collectors.toSet());
ScopeMappingRepresentation scopeMappingRep = null;
for (RoleModel scope : clientScopes) {
@ -232,7 +218,7 @@ public class ExportUtils {
currentClientTemplateScope.role(scope.getName());
}
}
}
});
if (clientScopeReps.size() > 0) {
rep.setClientScopeMappings(clientScopeReps);
@ -285,9 +271,8 @@ public class ExportUtils {
}
public static MultivaluedHashMap<String, ComponentExportRepresentation> exportComponents(RealmModel realm, String parentId) {
List<ComponentModel> componentList = realm.getComponents(parentId);
MultivaluedHashMap<String, ComponentExportRepresentation> components = new MultivaluedHashMap<>();
for (ComponentModel component : componentList) {
realm.getComponentsStream(parentId).forEach(component -> {
ComponentExportRepresentation compRep = new ComponentExportRepresentation();
compRep.setId(component.getId());
compRep.setProviderId(component.getProviderId());
@ -296,7 +281,7 @@ public class ExportUtils {
compRep.setSubType(component.getSubType());
compRep.setSubComponents(exportComponents(realm, component.getId()));
components.add(component.getProviderType(), compRep);
}
});
return components;
}

View file

@ -68,12 +68,12 @@ public class ImportUtils {
// If master was imported, we may need to re-create realm management clients
if (masterImported) {
for (RealmModel realm : session.realms().getRealms()) {
if (realm.getMasterAdminClient() == null) {
logger.infof("Re-created management client in master realm for realm '%s'", realm.getName());
new RealmManager(session).setupMasterAdminManagement(realm);
}
}
session.realms().getRealmsStream()
.filter(realm -> realm.getMasterAdminClient() == null)
.forEach(realm -> {
logger.infof("Re-created management client in master realm for realm '%s'", realm.getName());
new RealmManager(session).setupMasterAdminManagement(realm);
});
}
}
@ -99,9 +99,7 @@ public class ImportUtils {
logger.infof("Realm '%s' already exists. Removing it before import", realmName);
if (Config.getAdminRealm().equals(realm.getId())) {
// Delete all masterAdmin apps due to foreign key constraints
for (RealmModel currRealm : model.getRealms()) {
currRealm.setMasterAdminClient(null);
}
model.getRealmsStream().forEach(r -> r.setMasterAdminClient(null));
}
// TODO: For migration between versions, it should be possible to delete just realm but keep it's users
model.removeRealm(realm.getId());

View file

@ -31,6 +31,7 @@ import org.keycloak.representations.idm.RealmRepresentation;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@ -47,7 +48,7 @@ public abstract class MultipleStepsExportProvider implements ExportProvider {
@Override
public void run(KeycloakSession session) {
List<RealmModel> realms = session.realms().getRealms();
List<RealmModel> realms = session.realms().getRealmsStream().collect(Collectors.toList());
holder.realms = realms;
}

View file

@ -27,9 +27,10 @@ import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.services.resources.account.AccountFormService;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@ -39,41 +40,36 @@ public class AccountFederatedIdentityBean {
private static OrderedModel.OrderedModelComparator<FederatedIdentityEntry> IDP_COMPARATOR_INSTANCE = new OrderedModel.OrderedModelComparator<>();
private final List<FederatedIdentityEntry> identities = new ArrayList<>();
private final List<FederatedIdentityEntry> identities;
private final boolean removeLinkPossible;
private final KeycloakSession session;
public AccountFederatedIdentityBean(KeycloakSession session, RealmModel realm, UserModel user, URI baseUri, String stateChecker) {
this.session = session;
List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
Set<FederatedIdentityModel> identities = session.users().getFederatedIdentities(user, realm);
int availableIdentities = 0;
if (identityProviders != null && !identityProviders.isEmpty()) {
for (IdentityProviderModel provider : identityProviders) {
if (!provider.isEnabled()) {
continue;
}
String providerId = provider.getAlias();
AtomicInteger availableIdentities = new AtomicInteger(0);
this.identities = realm.getIdentityProvidersStream()
.filter(IdentityProviderModel::isEnabled)
.map(provider -> {
String providerId = provider.getAlias();
FederatedIdentityModel identity = getIdentity(identities, providerId);
FederatedIdentityModel identity = getIdentity(identities, providerId);
if (identity != null) {
availableIdentities++;
}
if (identity != null) {
availableIdentities.getAndIncrement();
}
String displayName = KeycloakModelUtils.getIdentityProviderDisplayName(session, provider);
FederatedIdentityEntry entry = new FederatedIdentityEntry(identity, displayName, provider.getAlias(), provider.getAlias(),
provider.getConfig() != null ? provider.getConfig().get("guiOrder") : null);
this.identities.add(entry);
}
}
this.identities.sort(IDP_COMPARATOR_INSTANCE);
String displayName = KeycloakModelUtils.getIdentityProviderDisplayName(session, provider);
return new FederatedIdentityEntry(identity, displayName, provider.getAlias(), provider.getAlias(),
provider.getConfig() != null ? provider.getConfig().get("guiOrder") : null);
})
.sorted(IDP_COMPARATOR_INSTANCE)
.collect(Collectors.toList());
// Removing last social provider is not possible if you don't have other possibility to authenticate
this.removeLinkPossible = availableIdentities > 1 || user.getFederationLink() != null || AccountFormService.isPasswordSet(session, realm, user);
this.removeLinkPossible = availableIdentities.get() > 1 || user.getFederationLink() != null || AccountFormService.isPasswordSet(session, realm, user);
}
private FederatedIdentityModel getIdentity(Set<FederatedIdentityModel> identities, String providerId) {

View file

@ -19,6 +19,7 @@ package org.keycloak.forms.account.freemarker.model;
import org.keycloak.models.RealmModel;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author <a href="mailto:gerbermichi@me.com">Michael Gerber</a>
@ -58,7 +59,7 @@ public class RealmBean {
}
public Set<String> getSupportedLocales(){
return realm.getSupportedLocales();
return realm.getSupportedLocalesStream().collect(Collectors.toSet());
}
public boolean isEditUsernameAllowed() {

View file

@ -398,8 +398,8 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
if (realm != null) {
attributes.put("realm", new RealmBean(realm));
List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
identityProviders = LoginFormsUtil.filterIdentityProviders(identityProviders, session, realm, attributes, formData, context);
List<IdentityProviderModel> identityProviders = LoginFormsUtil
.filterIdentityProviders(realm.getIdentityProvidersStream(), session, context);
attributes.put("social", new IdentityProviderBean(realm, session, identityProviders, baseUriWithCodeAndClientId));
attributes.put("url", new UrlBean(realm, theme, baseUri, this.actionUri));

View file

@ -36,6 +36,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Various util methods, so the logic is not hardcoded in freemarker beans
@ -78,8 +79,7 @@ public class LoginFormsUtil {
}
}
public static List<IdentityProviderModel> filterIdentityProviders(List<IdentityProviderModel> providers, KeycloakSession session, RealmModel realm,
Map<String, Object> attributes, MultivaluedMap<String, String> formData, AuthenticationFlowContext context) {
public static List<IdentityProviderModel> filterIdentityProviders(Stream<IdentityProviderModel> providers, KeycloakSession session, AuthenticationFlowContext context) {
if (context != null) {
AuthenticationSessionModel authSession = context.getAuthenticationSession();
@ -87,11 +87,11 @@ public class LoginFormsUtil {
if (serializedCtx != null) {
IdentityProviderModel idp = serializedCtx.deserialize(session, authSession).getIdpConfig();
return providers.stream()
return providers
.filter(p -> !Objects.equals(p.getAlias(), idp.getAlias()))
.collect(Collectors.toList());
}
}
return providers;
return providers.collect(Collectors.toList());
}
}

View file

@ -17,9 +17,10 @@
package org.keycloak.forms.login.freemarker.model;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredCredentialModel;
import org.keycloak.representations.idm.CredentialRepresentation;
import java.util.Objects;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@ -86,12 +87,8 @@ public class RealmBean {
}
public boolean isPassword() {
for (RequiredCredentialModel r : realm.getRequiredCredentials()) {
if (r.getType().equals(CredentialRepresentation.PASSWORD)) {
return true;
}
}
return false;
return realm.getRequiredCredentialsStream()
.anyMatch(r -> Objects.equals(r.getType(), CredentialRepresentation.PASSWORD));
}
}

View file

@ -31,11 +31,8 @@ import javax.crypto.SecretKey;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -246,22 +243,22 @@ public class DefaultKeyManager implements KeyManager {
private List<KeyProvider> getProviders(RealmModel realm) {
List<KeyProvider> providers = providersMap.get(realm.getId());
if (providers == null) {
providers = new LinkedList<>();
List<ComponentModel> components = new LinkedList<>(realm.getComponents(realm.getId(), KeyProvider.class.getName()));
components.sort(new ProviderComparator());
for (ComponentModel c : components) {
try {
ProviderFactory<KeyProvider> f = session.getKeycloakSessionFactory().getProviderFactory(KeyProvider.class, c.getProviderId());
KeyProviderFactory factory = (KeyProviderFactory) f;
KeyProvider provider = factory.create(session, c);
session.enlistForClose(provider);
providers.add(provider);
} catch (Throwable t) {
logger.errorv(t, "Failed to load provider {0}", c.getId());
}
}
providers = realm.getComponentsStream(realm.getId(), KeyProvider.class.getName())
.sorted(new ProviderComparator())
.map(c -> {
try {
ProviderFactory<KeyProvider> f = session.getKeycloakSessionFactory().getProviderFactory(KeyProvider.class, c.getProviderId());
KeyProviderFactory factory = (KeyProviderFactory) f;
KeyProvider provider = factory.create(session, c);
session.enlistForClose(provider);
return provider;
} catch (Throwable t) {
logger.errorv(t, "Failed to load provider {0}", c.getId());
return null;
}
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
providersMap.put(realm.getId(), providers);
}

View file

@ -20,17 +20,13 @@ import org.jboss.logging.Logger;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.util.CookieHelper;
import org.keycloak.sessions.AuthenticationSessionModel;
import org.keycloak.storage.ReadOnlyException;
import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.UriInfo;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.stream.Collectors;
public class DefaultLocaleSelectorProvider implements LocaleSelectorProvider {
@ -168,19 +164,19 @@ public class DefaultLocaleSelectorProvider implements LocaleSelectorProvider {
}
private Locale findLocale(RealmModel realm, String... localeStrings) {
Set<String> supportedLocales = realm.getSupportedLocales();
List<Locale> supportedLocales = realm.getSupportedLocalesStream()
.map(Locale::forLanguageTag).collect(Collectors.toList());
for (String localeString : localeStrings) {
if (localeString != null) {
Locale result = null;
Locale search = Locale.forLanguageTag(localeString);
for (String languageTag : supportedLocales) {
Locale locale = Locale.forLanguageTag(languageTag);
if (locale.getLanguage().equals(search.getLanguage())) {
if (search.getCountry().equals("") ^ locale.getCountry().equals("") && result == null) {
result = locale;
for (Locale supportedLocale : supportedLocales) {
if (supportedLocale.getLanguage().equals(search.getLanguage())) {
if (search.getCountry().equals("") ^ supportedLocale.getCountry().equals("") && result == null) {
result = supportedLocale;
}
if (locale.getCountry().equals(search.getCountry())) {
return locale;
if (supportedLocale.getCountry().equals(search.getCountry())) {
return supportedLocale;
}
}
}

View file

@ -47,6 +47,8 @@ import java.net.URI;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -119,13 +121,10 @@ public class OIDCWellKnownProvider implements WellKnownProvider {
config.setClaimTypesSupported(DEFAULT_CLAIM_TYPES_SUPPORTED);
config.setClaimsParameterSupported(true);
List<ClientScopeModel> scopes = realm.getClientScopes();
List<String> scopeNames = new LinkedList<>();
for (ClientScopeModel clientScope : scopes) {
if (OIDCLoginProtocol.LOGIN_PROTOCOL.equals(clientScope.getProtocol())) {
scopeNames.add(clientScope.getName());
}
}
List<String> scopeNames = realm.getClientScopesStream()
.filter(clientScope -> Objects.equals(OIDCLoginProtocol.LOGIN_PROTOCOL, clientScope.getProtocol()))
.map(ClientScopeModel::getName)
.collect(Collectors.toList());
scopeNames.add(0, OAuth2Constants.SCOPE_OPENID);
config.setScopesSupported(scopeNames);

View file

@ -25,8 +25,6 @@ import org.keycloak.TokenCategory;
import org.keycloak.TokenVerifier;
import org.keycloak.broker.oidc.OIDCIdentityProvider;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.broker.provider.IdentityProvider;
import org.keycloak.broker.provider.IdentityProviderFactory;
import org.keycloak.cluster.ClusterProvider;
import org.keycloak.common.ClientConnection;
import org.keycloak.common.VerificationException;
@ -44,7 +42,6 @@ import org.keycloak.models.AuthenticatedClientSessionModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.ClientSessionContext;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
@ -78,7 +75,6 @@ import org.keycloak.services.util.MtlsHoKTokenUtil;
import org.keycloak.sessions.AuthenticationSessionModel;
import org.keycloak.util.TokenUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
@ -1092,13 +1088,14 @@ public class TokenManager {
}
LogoutToken logoutToken = logoutTokenOptional.get();
List<OIDCIdentityProvider> identityProviders = getOIDCIdentityProviders(realm, session);
List<OIDCIdentityProvider> identityProviders = getOIDCIdentityProviders(realm, session).collect(Collectors.toList());
if (identityProviders.isEmpty()) {
return LogoutTokenValidationCode.COULD_NOT_FIND_IDP;
}
List<OIDCIdentityProvider> validOidcIdentityProviders = validateLogoutTokenAgainstIdpProvider(identityProviders, encodedLogoutToken, logoutToken);
if (validOidcIdentityProviders.isEmpty()) {
Stream<OIDCIdentityProvider> validOidcIdentityProviders =
validateLogoutTokenAgainstIdpProvider(identityProviders.stream(), encodedLogoutToken, logoutToken);
if (validOidcIdentityProviders.count() == 0) {
return LogoutTokenValidationCode.TOKEN_VERIFICATION_WITH_IDP_FAILED;
}
@ -1135,43 +1132,37 @@ public class TokenManager {
}
public List<OIDCIdentityProvider> getValidOIDCIdentityProvidersForBackchannelLogout(RealmModel realm, KeycloakSession session, String encodedLogoutToken, LogoutToken logoutToken) {
List<OIDCIdentityProvider> identityProviders = getOIDCIdentityProviders(realm, session);
return validateLogoutTokenAgainstIdpProvider(identityProviders, encodedLogoutToken, logoutToken);
public Stream<OIDCIdentityProvider> getValidOIDCIdentityProvidersForBackchannelLogout(RealmModel realm, KeycloakSession session, String encodedLogoutToken, LogoutToken logoutToken) {
return validateLogoutTokenAgainstIdpProvider(getOIDCIdentityProviders(realm, session), encodedLogoutToken, logoutToken);
}
public List<OIDCIdentityProvider> validateLogoutTokenAgainstIdpProvider(List<OIDCIdentityProvider> oidcIdps, String encodedLogoutToken, LogoutToken logoutToken) {
List<OIDCIdentityProvider> validIdps = new ArrayList<>();
for (OIDCIdentityProvider oidcIdp : oidcIdps) {
if (oidcIdp.getConfig().getIssuer() != null) {
if (oidcIdp.isIssuer(logoutToken.getIssuer(), null)) {
try {
oidcIdp.validateToken(encodedLogoutToken);
validIdps.add(oidcIdp);
} catch (IdentityBrokerException e) {
logger.debugf("LogoutToken verification with identity provider failed", e.getMessage());
}
}
}
}
return validIdps;
public Stream<OIDCIdentityProvider> validateLogoutTokenAgainstIdpProvider(Stream<OIDCIdentityProvider> oidcIdps, String encodedLogoutToken, LogoutToken logoutToken) {
return oidcIdps
.filter(oidcIdp -> oidcIdp.getConfig().getIssuer() != null)
.filter(oidcIdp -> oidcIdp.isIssuer(logoutToken.getIssuer(), null))
.filter(oidcIdp -> {
try {
oidcIdp.validateToken(encodedLogoutToken);
return true;
} catch (IdentityBrokerException e) {
logger.debugf("LogoutToken verification with identity provider failed", e.getMessage());
return false;
}
});
}
private List<OIDCIdentityProvider> getOIDCIdentityProviders(RealmModel realm, KeycloakSession session) {
List<OIDCIdentityProvider> availableProviders = new ArrayList<>();
private Stream<OIDCIdentityProvider> getOIDCIdentityProviders(RealmModel realm, KeycloakSession session) {
try {
for (IdentityProviderModel idpModel : realm.getIdentityProviders()) {
IdentityProviderFactory factory = IdentityBrokerService.getIdentityProviderFactory(session, idpModel);
IdentityProvider identityProvider = factory.create(session, idpModel);
if (identityProvider instanceof OIDCIdentityProvider) {
availableProviders.add(((OIDCIdentityProvider) identityProvider));
}
}
return realm.getIdentityProvidersStream()
.map(idpModel ->
IdentityBrokerService.getIdentityProviderFactory(session, idpModel).create(session, idpModel))
.filter(OIDCIdentityProvider.class::isInstance)
.map(OIDCIdentityProvider.class::cast);
} catch (IdentityBrokerException e) {
logger.warnf("LogoutToken verification with identity provider failed", e.getMessage());
}
return availableProviders;
return Stream.empty();
}
private boolean checkLogoutTokenForEvents(LogoutToken logoutToken) {

View file

@ -46,7 +46,6 @@ import org.keycloak.representations.RefreshToken;
import org.keycloak.services.ErrorPage;
import org.keycloak.services.ErrorResponseException;
import org.keycloak.services.clientpolicy.ClientPolicyException;
import org.keycloak.services.clientpolicy.DefaultClientPolicyManager;
import org.keycloak.services.clientpolicy.LogoutRequestContext;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.UserSessionManager;
@ -63,7 +62,8 @@ import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import java.util.List;
import java.util.stream.Collectors;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -270,10 +270,9 @@ public class LogoutEndpoint {
LogoutToken logoutToken = tokenManager.toLogoutToken(encodedLogoutToken).get();
List<String> identityProviderAliases = tokenManager.getValidOIDCIdentityProvidersForBackchannelLogout(realm,
session, encodedLogoutToken, logoutToken).stream()
.map(idp -> idp.getConfig().getAlias())
.collect(Collectors.toList());
Stream<String> identityProviderAliases = tokenManager.getValidOIDCIdentityProvidersForBackchannelLogout(realm,
session, encodedLogoutToken, logoutToken)
.map(idp -> idp.getConfig().getAlias());
boolean logoutOfflineSessions = Boolean.parseBoolean(logoutToken.getEvents()
.getOrDefault(TokenUtil.TOKEN_BACKCHANNEL_LOGOUT_EVENT_REVOKE_OFFLINE_TOKENS, false).toString());
@ -313,10 +312,10 @@ public class LogoutEndpoint {
}
private BackchannelLogoutResponse backchannelLogoutWithSessionId(String sessionId,
List<String> identityProviderAliases, boolean logoutOfflineSessions) {
BackchannelLogoutResponse backchannelLogoutResponse = new BackchannelLogoutResponse();
backchannelLogoutResponse.setLocalLogoutSucceeded(true);
for (String identityProviderAlias : identityProviderAliases) {
Stream<String> identityProviderAliases, boolean logoutOfflineSessions) {
AtomicReference<BackchannelLogoutResponse> backchannelLogoutResponse = new AtomicReference<>(new BackchannelLogoutResponse());
backchannelLogoutResponse.get().setLocalLogoutSucceeded(true);
identityProviderAliases.forEach(identityProviderAlias -> {
UserSessionModel userSession = session.sessions().getUserSessionByBrokerSessionId(realm,
identityProviderAlias + "." + sessionId);
@ -325,11 +324,11 @@ public class LogoutEndpoint {
}
if (userSession != null) {
backchannelLogoutResponse = logoutUserSession(userSession);
backchannelLogoutResponse.set(logoutUserSession(userSession));
}
}
});
return backchannelLogoutResponse;
return backchannelLogoutResponse.get();
}
private void logoutOfflineUserSession(String brokerSessionId) {
@ -341,10 +340,11 @@ public class LogoutEndpoint {
}
private BackchannelLogoutResponse backchannelLogoutFederatedUserId(String federatedUserId,
List<String> identityProviderAliases, boolean logoutOfflineSessions) {
Stream<String> identityProviderAliases,
boolean logoutOfflineSessions) {
BackchannelLogoutResponse backchannelLogoutResponse = new BackchannelLogoutResponse();
backchannelLogoutResponse.setLocalLogoutSucceeded(true);
for (String identityProviderAlias : identityProviderAliases) {
identityProviderAliases.forEach(identityProviderAlias -> {
List<UserSessionModel> userSessions = session.sessions().getUserSessionByBrokerUserId(realm,
identityProviderAlias + "." + federatedUserId);
@ -360,7 +360,7 @@ public class LogoutEndpoint {
userBackchannelLogoutResponse.getClientResponses()
.forEach(backchannelLogoutResponse::addClientResponses);
}
}
});
return backchannelLogoutResponse;
}

View file

@ -127,8 +127,10 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static org.keycloak.models.ImpersonationSessionNote.IMPERSONATOR_ID;
import static org.keycloak.models.ImpersonationSessionNote.IMPERSONATOR_USERNAME;
@ -1051,33 +1053,34 @@ public class TokenEndpoint {
}
public Response exchangeExternalToken(String issuer, String subjectToken) {
ExchangeExternalToken externalIdp = null;
IdentityProviderModel externalIdpModel = null;
AtomicReference<ExchangeExternalToken> externalIdp = new AtomicReference<>(null);
AtomicReference<IdentityProviderModel> externalIdpModel = new AtomicReference<>(null);
for (IdentityProviderModel idpModel : realm.getIdentityProviders()) {
realm.getIdentityProvidersStream().filter(idpModel -> {
IdentityProviderFactory factory = IdentityBrokerService.getIdentityProviderFactory(session, idpModel);
IdentityProvider idp = factory.create(session, idpModel);
if (idp instanceof ExchangeExternalToken) {
ExchangeExternalToken external = (ExchangeExternalToken) idp;
if (idpModel.getAlias().equals(issuer) || external.isIssuer(issuer, formParams)) {
externalIdp = external;
externalIdpModel = idpModel;
break;
externalIdp.set(external);
externalIdpModel.set(idpModel);
return true;
}
}
}
return false;
}).findFirst();
if (externalIdp == null) {
if (externalIdp.get() == null) {
event.error(Errors.INVALID_ISSUER);
throw new CorsErrorResponseException(cors, Errors.INVALID_ISSUER, "Invalid " + OAuth2Constants.SUBJECT_ISSUER + " parameter", Response.Status.BAD_REQUEST);
}
if (!AdminPermissions.management(session, realm).idps().canExchangeTo(client, externalIdpModel)) {
if (!AdminPermissions.management(session, realm).idps().canExchangeTo(client, externalIdpModel.get())) {
event.detail(Details.REASON, "client not allowed to exchange subject_issuer");
event.error(Errors.NOT_ALLOWED);
throw new CorsErrorResponseException(cors, OAuthErrorException.ACCESS_DENIED, "Client not allowed to exchange", Response.Status.FORBIDDEN);
}
BrokeredIdentityContext context = externalIdp.exchangeExternal(event, formParams);
BrokeredIdentityContext context = externalIdp.get().exchangeExternal(event, formParams);
if (context == null) {
event.error(Errors.INVALID_ISSUER);
throw new CorsErrorResponseException(cors, Errors.INVALID_ISSUER, "Invalid " + OAuth2Constants.SUBJECT_ISSUER + " parameter", Response.Status.BAD_REQUEST);
@ -1086,10 +1089,10 @@ public class TokenEndpoint {
UserModel user = importUserFromExternalIdentity(context);
UserSessionModel userSession = session.sessions().createUserSession(realm, user, user.getUsername(), clientConnection.getRemoteAddr(), "external-exchange", false, null, null);
externalIdp.exchangeExternalComplete(userSession, context, formParams);
externalIdp.get().exchangeExternalComplete(userSession, context, formParams);
// this must exist so that we can obtain access token from user session if idp's store tokens is off
userSession.setNote(IdentityProvider.EXTERNAL_IDENTITY_PROVIDER, externalIdpModel.getAlias());
userSession.setNote(IdentityProvider.EXTERNAL_IDENTITY_PROVIDER, externalIdpModel.get().getAlias());
userSession.setNote(IdentityProvider.FEDERATED_ACCESS_TOKEN, subjectToken);
return exchangeClientToClient(user, userSession);
@ -1106,13 +1109,12 @@ public class TokenEndpoint {
//session.getContext().setClient(authenticationSession.getClient());
context.getIdp().preprocessFederatedIdentity(session, realm, context);
Set<IdentityProviderMapperModel> mappers = realm.getIdentityProviderMappersByAlias(context.getIdpConfig().getAlias());
if (mappers != null) {
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
for (IdentityProviderMapperModel mapper : mappers) {
IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
target.preprocessFederatedIdentity(session, realm, mapper, context);
}
Set<IdentityProviderMapperModel> mappers = realm.getIdentityProviderMappersByAliasStream(context.getIdpConfig().getAlias())
.collect(Collectors.toSet());
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
for (IdentityProviderMapperModel mapper : mappers) {
IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
target.preprocessFederatedIdentity(session, realm, mapper, context);
}
FederatedIdentityModel federatedIdentityModel = new FederatedIdentityModel(providerId, context.getId(),
@ -1163,12 +1165,10 @@ public class TokenEndpoint {
session.users().addFederatedIdentity(realm, user, federatedIdentityModel);
context.getIdp().importNewUser(session, realm, user, context);
if (mappers != null) {
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
for (IdentityProviderMapperModel mapper : mappers) {
IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
target.importNewUser(session, realm, user, mapper, context);
}
for (IdentityProviderMapperModel mapper : mappers) {
IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
target.importNewUser(session, realm, user, mapper, context);
}
if (context.getIdpConfig().isTrustEmail() && !Validation.isBlank(user.getEmail())) {
@ -1188,12 +1188,10 @@ public class TokenEndpoint {
}
context.getIdp().updateBrokeredUser(session, realm, user, context);
if (mappers != null) {
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
for (IdentityProviderMapperModel mapper : mappers) {
IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
IdentityProviderMapperSyncModeDelegate.delegateUpdateBrokeredUser(session, realm, user, mapper, context, target);
}
for (IdentityProviderMapperModel mapper : mappers) {
IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
IdentityProviderMapperSyncModeDelegate.delegateUpdateBrokeredUser(session, realm, user, mapper, context, target);
}
}
return user;

View file

@ -22,7 +22,6 @@ import org.keycloak.authentication.ClientAuthenticator;
import org.keycloak.authentication.ClientAuthenticatorFactory;
import org.keycloak.authorization.admin.AuthorizationService;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.Constants;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
@ -111,15 +110,15 @@ public class KeycloakOIDCClientInstallation implements ClientInstallationProvide
// Check if there is client scope with audience protocol mapper created for particular client. If yes, admin wants verifying token audience
String clientId = client.getClientId();
for (ClientScopeModel clientScope : client.getRealm().getClientScopes()) {
return client.getRealm().getClientScopesStream().anyMatch(clientScope -> {
for (ProtocolMapperModel protocolMapper : clientScope.getProtocolMappers()) {
if (AudienceProtocolMapper.PROVIDER_ID.equals(protocolMapper.getProtocolMapper()) && (clientId.equals(protocolMapper.getConfig().get(AudienceProtocolMapper.INCLUDED_CLIENT_AUDIENCE)))) {
if (AudienceProtocolMapper.PROVIDER_ID.equals(protocolMapper.getProtocolMapper()) &&
(clientId.equals(protocolMapper.getConfig().get(AudienceProtocolMapper.INCLUDED_CLIENT_AUDIENCE)))) {
return true;
}
}
}
return false;
return false;
});
}

View file

@ -45,6 +45,7 @@ import javax.xml.soap.SOAPHeaderElement;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Objects;
/**
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
@ -149,12 +150,9 @@ public class SamlEcpProfileService extends SamlService {
@Override
protected AuthenticationFlowModel getAuthenticationFlow(AuthenticationSessionModel authSession) {
for (AuthenticationFlowModel flowModel : realm.getAuthenticationFlows()) {
if (flowModel.getAlias().equals(DefaultAuthenticationFlows.SAML_ECP_FLOW)) {
return flowModel;
}
}
throw new RuntimeException("Could not resolve authentication flow for SAML ECP Profile.");
return realm.getAuthenticationFlowsStream()
.filter(flow -> Objects.equals(flow.getAlias(), DefaultAuthenticationFlows.SAML_ECP_FLOW))
.findFirst()
.orElseThrow(() -> new RuntimeException("Could not resolve authentication flow for SAML ECP Profile."));
}
}

View file

@ -17,20 +17,13 @@
package org.keycloak.services.clientpolicy;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
import org.jboss.logging.Logger;
import org.keycloak.common.Profile;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.services.clientpolicy.ClientPolicyContext;
import org.keycloak.services.clientpolicy.ClientPolicyException;
import org.keycloak.services.clientpolicy.ClientPolicyManager;
import org.keycloak.services.clientpolicy.ClientPolicyProvider;
import org.keycloak.services.clientpolicy.condition.ClientPolicyConditionProvider;
import org.keycloak.services.clientpolicy.executor.ClientPolicyExecutorProvider;
@ -67,18 +60,20 @@ public class DefaultClientPolicyManager implements ClientPolicyManager {
private List<ClientPolicyProvider> getProviders(RealmModel realm) {
List<ClientPolicyProvider> providers = providersMap.get(realm.getId());
if (providers == null) {
providers = new LinkedList<>();
List<ComponentModel> policyModels = realm.getComponents(realm.getId(), ClientPolicyProvider.class.getName());
for (ComponentModel policyModel : policyModels) {
try {
ClientPolicyProvider policy = session.getProvider(ClientPolicyProvider.class, policyModel);
ClientPolicyLogger.logv(logger, "Loaded Policy Name = {0}", policyModel.getName());
session.enlistForClose(policy);
providers.add(policy);
} catch (Throwable t) {
logger.errorv(t, "Failed to load provider {0}", policyModel.getId());
}
}
providers = realm.getComponentsStream(realm.getId(), ClientPolicyProvider.class.getName())
.map(policyModel -> {
try {
ClientPolicyProvider policy = session.getProvider(ClientPolicyProvider.class, policyModel);
ClientPolicyLogger.logv(logger, "Loaded Policy Name = {0}", policyModel.getName());
session.enlistForClose(policy);
return policy;
} catch (Throwable t) {
logger.errorv(t, "Failed to load provider {0}", policyModel.getId());
return null;
}
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
providersMap.put(realm.getId(), providers);
} else {
ClientPolicyLogger.log(logger, "Use cached policies.");

View file

@ -22,7 +22,7 @@ import org.keycloak.component.ComponentModel;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ClientRegistrationPolicyException extends Exception {
public class ClientRegistrationPolicyException extends RuntimeException {
private ComponentModel policyModel;

View file

@ -17,9 +17,7 @@
package org.keycloak.services.clientregistration.policy;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.Objects;
import org.jboss.logging.Logger;
import org.keycloak.component.ComponentModel;
@ -97,36 +95,34 @@ public class ClientRegistrationPolicyManager {
private static void triggerPolicies(KeycloakSession session, ClientRegistrationProvider provider, RegistrationAuth authType, String opDescription, ClientRegOperation op) throws ClientRegistrationPolicyException {
private static void triggerPolicies(KeycloakSession session, ClientRegistrationProvider provider, RegistrationAuth authType,
String opDescription, ClientRegOperation op) throws ClientRegistrationPolicyException {
RealmModel realm = session.getContext().getRealm();
String policyTypeKey = getComponentTypeKey(authType);
List<ComponentModel> policyModels = realm.getComponents(realm.getId(), ClientRegistrationPolicy.class.getName());
realm.getComponentsStream(realm.getId(), ClientRegistrationPolicy.class.getName())
.filter(componentModel -> Objects.equals(componentModel.getSubType(), policyTypeKey))
.forEach(policyModel -> runPolicy(policyModel, session, provider, opDescription, op));
}
policyModels = policyModels.stream().filter((ComponentModel model) -> {
private static void runPolicy(ComponentModel policyModel, KeycloakSession session, ClientRegistrationProvider provider,
String opDescription, ClientRegOperation op) throws ClientRegistrationPolicyException {
ClientRegistrationPolicy policy = session.getProvider(ClientRegistrationPolicy.class, policyModel);
if (policy == null) {
throw new ClientRegistrationPolicyException("Policy of type '" + policyModel.getProviderId() + "' not found");
}
return policyTypeKey.equals(model.getSubType());
if (logger.isTraceEnabled()) {
logger.tracef("Running policy '%s' %s", policyModel.getName(), opDescription);
}
}).collect(Collectors.toList());
for (ComponentModel policyModel : policyModels) {
ClientRegistrationPolicy policy = session.getProvider(ClientRegistrationPolicy.class, policyModel);
if (policy == null) {
throw new ClientRegistrationPolicyException("Policy of type '" + policyModel.getProviderId() + "' not found");
}
if (logger.isTraceEnabled()) {
logger.tracef("Running policy '%s' %s", policyModel.getName(), opDescription);
}
try {
op.run(policy);
} catch (ClientRegistrationPolicyException crpe) {
provider.getEvent().detail(Details.CLIENT_REGISTRATION_POLICY, policyModel.getName());
crpe.setPolicyModel(policyModel);
ServicesLogger.LOGGER.clientRegistrationRequestRejected(opDescription, crpe.getMessage());
throw crpe;
}
try {
op.run(policy);
} catch (ClientRegistrationPolicyException crpe) {
provider.getEvent().detail(Details.CLIENT_REGISTRATION_POLICY, policyModel.getName());
crpe.setPolicyModel(policyModel);
ServicesLogger.LOGGER.clientRegistrationRequestRejected(opDescription, crpe.getMessage());
throw crpe;
}
}

View file

@ -19,7 +19,6 @@ package org.keycloak.services.clientregistration.policy;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.keycloak.component.ComponentModel;
import org.keycloak.models.RealmModel;
@ -57,10 +56,9 @@ public class DefaultClientRegistrationPolicies {
public static void addDefaultPolicies(RealmModel realm) {
String anonPolicyType = ClientRegistrationPolicyManager.getComponentTypeKey(RegistrationAuth.ANONYMOUS);
String authPolicyType = ClientRegistrationPolicyManager.getComponentTypeKey(RegistrationAuth.AUTHENTICATED);
List<ComponentModel> policies = realm.getComponents(realm.getId(), ClientRegistrationPolicy.class.getName());
// Probably an issue if admin removes all policies intentionally...
if (policies == null ||policies.isEmpty()) {
if (realm.getComponentsStream(realm.getId(), ClientRegistrationPolicy.class.getName()).count() == 0) {
addAnonymousPolicies(realm, anonPolicyType);
addAuthPolicies(realm, authPolicyType);
}

View file

@ -124,13 +124,7 @@ public class ClientScopesClientRegistrationPolicy implements ClientRegistrationP
// If allowDefaultScopes, then realm default scopes are allowed as default scopes (+ optional scopes are allowed as optional scopes)
boolean allowDefaultScopes = componentModel.get(ClientScopesClientRegistrationPolicyFactory.ALLOW_DEFAULT_SCOPES, true);
if (allowDefaultScopes) {
List<String> scopeNames = realm.getDefaultClientScopes(defaultScopes).stream().map((ClientScopeModel clientScope) -> {
return clientScope.getName();
}).collect(Collectors.toList());
allAllowed.addAll(scopeNames);
allAllowed.addAll(realm.getDefaultClientScopesStream(defaultScopes).map(ClientScopeModel::getName).collect(Collectors.toList()));
}
return allAllowed;

View file

@ -87,13 +87,7 @@ public class ClientScopesClientRegistrationPolicyFactory extends AbstractClientR
if (realm == null) {
return Collections.emptyList();
} else {
List<ClientScopeModel> clientScopes = realm.getClientScopes();
return clientScopes.stream().map((ClientScopeModel clientScope) -> {
return clientScope.getName();
}).collect(Collectors.toList());
return realm.getClientScopesStream().map(ClientScopeModel::getName).collect(Collectors.toList());
}
}

View file

@ -884,7 +884,7 @@ public class AuthenticationManager {
public static Response nextActionAfterAuthentication(KeycloakSession session, AuthenticationSessionModel authSession,
ClientConnection clientConnection,
HttpRequest request, UriInfo uriInfo, EventBuilder event) {
Response requiredAction = actionRequired(session, authSession, clientConnection, request, uriInfo, event);
Response requiredAction = actionRequired(session, authSession, request, event);
if (requiredAction != null) return requiredAction;
return finishedRequiredActions(session, authSession, null, clientConnection, request, uriInfo, event);
@ -962,13 +962,12 @@ public class AuthenticationManager {
// Return null if action is not required. Or the name of the requiredAction in case it is required.
public static String nextRequiredAction(final KeycloakSession session, final AuthenticationSessionModel authSession,
final ClientConnection clientConnection,
final HttpRequest request, final UriInfo uriInfo, final EventBuilder event) {
final HttpRequest request, final EventBuilder event) {
final RealmModel realm = authSession.getRealm();
final UserModel user = authSession.getAuthenticatedUser();
final ClientModel client = authSession.getClient();
evaluateRequiredActionTriggers(session, authSession, clientConnection, request, uriInfo, event, realm, user);
evaluateRequiredActionTriggers(session, authSession, request, event, realm, user);
if (!user.getRequiredActions().isEmpty()) {
return user.getRequiredActions().iterator().next();
@ -1018,14 +1017,12 @@ public class AuthenticationManager {
public static Response actionRequired(final KeycloakSession session, final AuthenticationSessionModel authSession,
final ClientConnection clientConnection,
final HttpRequest request, final UriInfo uriInfo, final EventBuilder event) {
final HttpRequest request, final EventBuilder event) {
final RealmModel realm = authSession.getRealm();
final UserModel user = authSession.getAuthenticatedUser();
final ClientModel client = authSession.getClient();
evaluateRequiredActionTriggers(session, authSession, clientConnection, request, uriInfo, event, realm, user);
evaluateRequiredActionTriggers(session, authSession, request, event, realm, user);
logger.debugv("processAccessCode: go to oauth page?: {0}", client.isConsentRequired());
@ -1142,10 +1139,11 @@ public class AuthenticationManager {
String kcAction = authSession.getClientNote(Constants.KC_ACTION);
if (kcAction != null) {
for (RequiredActionProviderModel m : realm.getRequiredActionProviders()) {
if (m.getProviderId().equals(kcAction)) {
return executeAction(session, authSession, m, request, event, realm, user, true);
}
Optional<RequiredActionProviderModel> requiredAction = realm.getRequiredActionProvidersStream()
.filter(m -> Objects.equals(m.getProviderId(), kcAction))
.findFirst();
if (requiredAction.isPresent()) {
return executeAction(session, authSession, requiredAction.get(), request, event, realm, user, true);
}
logger.debugv("Requested action {0} not configured for realm", kcAction);
@ -1230,40 +1228,53 @@ public class AuthenticationManager {
return actions;
}
public static void evaluateRequiredActionTriggers(final KeycloakSession session, final AuthenticationSessionModel authSession, final ClientConnection clientConnection, final HttpRequest request, final UriInfo uriInfo, final EventBuilder event, final RealmModel realm, final UserModel user) {
public static void evaluateRequiredActionTriggers(final KeycloakSession session, final AuthenticationSessionModel authSession,
final HttpRequest request, final EventBuilder event,
final RealmModel realm, final UserModel user) {
// see if any required actions need triggering, i.e. an expired password
for (RequiredActionProviderModel model : realm.getRequiredActionProviders()) {
if (!model.isEnabled()) continue;
RequiredActionFactory factory = (RequiredActionFactory)session.getKeycloakSessionFactory().getProviderFactory(RequiredActionProvider.class, model.getProviderId());
if (factory == null) {
throw new RuntimeException("Unable to find factory for Required Action: " + model.getProviderId() + " did you forget to declare it in a META-INF/services file?");
realm.getRequiredActionProvidersStream()
.filter(RequiredActionProviderModel::isEnabled)
.map(model -> toRequiredActionFactory(session, model))
.forEachOrdered(f -> evaluateRequiredAction(session, authSession, request, event, realm, user, f));
}
private static void evaluateRequiredAction(final KeycloakSession session, final AuthenticationSessionModel authSession,
final HttpRequest request, final EventBuilder event, final RealmModel realm,
final UserModel user, RequiredActionFactory factory) {
RequiredActionProvider provider = factory.create(session);
RequiredActionContextResult result = new RequiredActionContextResult(authSession, realm, event, session, request, user, factory) {
@Override
public void challenge(Response response) {
throw new RuntimeException("Not allowed to call challenge() within evaluateTriggers()");
}
RequiredActionProvider provider = factory.create(session);
RequiredActionContextResult result = new RequiredActionContextResult(authSession, realm, event, session, request, user, factory) {
@Override
public void challenge(Response response) {
throw new RuntimeException("Not allowed to call challenge() within evaluateTriggers()");
}
@Override
public void failure() {
throw new RuntimeException("Not allowed to call failure() within evaluateTriggers()");
}
@Override
public void failure() {
throw new RuntimeException("Not allowed to call failure() within evaluateTriggers()");
}
@Override
public void success() {
throw new RuntimeException("Not allowed to call success() within evaluateTriggers()");
}
@Override
public void success() {
throw new RuntimeException("Not allowed to call success() within evaluateTriggers()");
}
@Override
public void ignore() {
throw new RuntimeException("Not allowed to call ignore() within evaluateTriggers()");
}
};
@Override
public void ignore() {
throw new RuntimeException("Not allowed to call ignore() within evaluateTriggers()");
}
};
provider.evaluateTriggers(result);
provider.evaluateTriggers(result);
}
private static RequiredActionFactory toRequiredActionFactory(KeycloakSession session, RequiredActionProviderModel model) {
RequiredActionFactory factory = (RequiredActionFactory) session.getKeycloakSessionFactory()
.getProviderFactory(RequiredActionProvider.class, model.getProviderId());
if (factory == null) {
throw new RuntimeException("Unable to find factory for Required Action: "
+ model.getProviderId() + " did you forget to declare it in a META-INF/services file?");
}
return factory;
}
public static AuthResult verifyIdentityToken(KeycloakSession session, RealmModel realm, UriInfo uriInfo, ClientConnection connection, boolean checkActive, boolean checkTokenType,

View file

@ -52,7 +52,6 @@ import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.sessions.AuthenticationSessionProvider;
import org.keycloak.storage.UserStorageProviderModel;
import org.keycloak.services.clientregistration.policy.DefaultClientRegistrationPolicies;
import java.util.Collections;
@ -126,11 +125,11 @@ public class RealmManager {
}
protected void setupAuthenticationFlows(RealmModel realm) {
if (realm.getAuthenticationFlows().size() == 0) DefaultAuthenticationFlows.addFlows(realm);
if (realm.getAuthenticationFlowsStream().count() == 0) DefaultAuthenticationFlows.addFlows(realm);
}
protected void setupRequiredActions(RealmModel realm) {
if (realm.getRequiredActionProviders().size() == 0) DefaultRequiredActions.addActions(realm);
if (realm.getRequiredActionProvidersStream().count() == 0) DefaultRequiredActions.addActions(realm);
}
private void setupOfflineTokens(RealmModel realm, RealmRepresentation realmRep) {
@ -270,11 +269,9 @@ public class RealmManager {
}
// Refresh periodic sync tasks for configured storageProviders
List<UserStorageProviderModel> storageProviders = realm.getUserStorageProviders();
UserStorageSyncManager storageSync = new UserStorageSyncManager();
for (UserStorageProviderModel provider : storageProviders) {
storageSync.notifyToRefreshPeriodicSync(session, realm, provider, true);
}
realm.getUserStorageProvidersStream()
.forEachOrdered(provider -> storageSync.notifyToRefreshPeriodicSync(session, realm, provider, true));
}
return removed;
@ -576,11 +573,9 @@ public class RealmManager {
setupRequiredActions(realm);
// Refresh periodic sync tasks for configured storageProviders
List<UserStorageProviderModel> storageProviders = realm.getUserStorageProviders();
UserStorageSyncManager storageSync = new UserStorageSyncManager();
for (UserStorageProviderModel provider : storageProviders) {
storageSync.notifyToRefreshPeriodicSync(session, realm, provider, false);
}
realm.getUserStorageProvidersStream()
.forEachOrdered(provider -> storageSync.notifyToRefreshPeriodicSync(session, realm, provider, false));
setupAuthorizationServices(realm);
setupClientRegistrations(realm);

View file

@ -35,8 +35,9 @@ import org.keycloak.storage.user.ImportSynchronization;
import org.keycloak.storage.user.SynchronizationResult;
import org.keycloak.timer.TimerProvider;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.stream.Stream;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@ -58,16 +59,16 @@ public class UserStorageSyncManager {
@Override
public void run(KeycloakSession session) {
List<RealmModel> realms = session.realms().getRealmsWithProviderType(UserStorageProvider.class);
for (final RealmModel realm : realms) {
List<UserStorageProviderModel> providers = realm.getUserStorageProviders();
for (final UserStorageProviderModel provider : providers) {
Stream<RealmModel> realms = session.realms().getRealmsWithProviderTypeStream(UserStorageProvider.class);
realms.forEach(realm -> {
Stream<UserStorageProviderModel> providers = realm.getUserStorageProvidersStream();
providers.forEachOrdered(provider -> {
UserStorageProviderFactory factory = (UserStorageProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(UserStorageProvider.class, provider.getProviderId());
if (factory instanceof ImportSynchronization && provider.isImportEnabled()) {
refreshPeriodicSyncForProvider(sessionFactory, timer, provider, realm.getId());
}
}
}
});
});
ClusterProvider clusterProvider = session.getProvider(ClusterProvider.class);
clusterProvider.registerListener(USER_STORAGE_TASK_KEY, new UserStorageClusterListener(sessionFactory));
@ -254,20 +255,18 @@ public class UserStorageSyncManager {
@Override
public void run(KeycloakSession session) {
RealmModel persistentRealm = session.realms().getRealm(realmId);
List<UserStorageProviderModel> persistentFedProviders = persistentRealm.getUserStorageProviders();
for (UserStorageProviderModel persistentFedProvider : persistentFedProviders) {
if (provider.getId().equals(persistentFedProvider.getId())) {
// Update persistent provider in DB
int lastSync = Time.currentTime();
persistentFedProvider.setLastSync(lastSync);
persistentRealm.updateComponent(persistentFedProvider);
persistentRealm.getUserStorageProvidersStream()
.filter(persistentFedProvider -> Objects.equals(provider.getId(), persistentFedProvider.getId()))
.forEachOrdered(persistentFedProvider -> {
// Update persistent provider in DB
int lastSync = Time.currentTime();
persistentFedProvider.setLastSync(lastSync);
persistentRealm.updateComponent(persistentFedProvider);
// Update "cached" reference
provider.setLastSync(lastSync);
}
}
// Update "cached" reference
provider.setLastSync(lastSync);
});
}
});
}

View file

@ -51,7 +51,6 @@ import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionContext;
import org.keycloak.models.Constants;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.IdentityProviderSyncMode;
import org.keycloak.models.KeycloakSession;
@ -538,14 +537,12 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
session.getContext().setClient(authenticationSession.getClient());
context.getIdp().preprocessFederatedIdentity(session, realmModel, context);
Set<IdentityProviderMapperModel> mappers = realmModel.getIdentityProviderMappersByAlias(context.getIdpConfig().getAlias());
if (mappers != null) {
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
for (IdentityProviderMapperModel mapper : mappers) {
IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
target.preprocessFederatedIdentity(session, realmModel, mapper, context);
}
}
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
realmModel.getIdentityProviderMappersByAliasStream(context.getIdpConfig().getAlias()).forEach(mapper -> {
IdentityProviderMapper target = (IdentityProviderMapper) sessionFactory
.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
target.preprocessFederatedIdentity(session, realmModel, mapper, context);
});
FederatedIdentityModel federatedIdentityModel = new FederatedIdentityModel(providerId, context.getId(),
context.getUsername(), context.getToken());
@ -717,14 +714,12 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
logger.debugf("Registered new user '%s' after first login with identity provider '%s'. Identity provider username is '%s' . ", federatedUser.getUsername(), providerId, context.getUsername());
context.getIdp().importNewUser(session, realmModel, federatedUser, context);
Set<IdentityProviderMapperModel> mappers = realmModel.getIdentityProviderMappersByAlias(providerId);
if (mappers != null) {
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
for (IdentityProviderMapperModel mapper : mappers) {
IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
target.importNewUser(session, realmModel, federatedUser, mapper, context);
}
}
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
realmModel.getIdentityProviderMappersByAliasStream(providerId).forEach(mapper -> {
IdentityProviderMapper target = (IdentityProviderMapper) sessionFactory
.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
target.importNewUser(session, realmModel, federatedUser, mapper, context);
});
if (context.getIdpConfig().isTrustEmail() && !Validation.isBlank(federatedUser.getEmail()) && !Boolean.parseBoolean(authSession.getAuthNote(AbstractIdpAuthenticator.UPDATE_PROFILE_EMAIL_CHANGED))) {
logger.debugf("Email verified automatically after registration of user '%s' through Identity provider '%s' ", federatedUser.getUsername(), context.getIdpConfig().getAlias());
@ -861,7 +856,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
AuthenticationManager.setClientScopesInSession(authSession);
String nextRequiredAction = AuthenticationManager.nextRequiredAction(session, authSession, clientConnection, request, session.getContext().getUri(), event);
String nextRequiredAction = AuthenticationManager.nextRequiredAction(session, authSession, request, event);
if (nextRequiredAction != null) {
if ("true".equals(authSession.getAuthNote(AuthenticationProcessor.FORWARDED_PASSIVE_LOGIN))) {
logger.errorf("Required action %s found. Auth requests using prompt=none are incompatible with required actions", nextRequiredAction);
@ -1019,15 +1014,12 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
// Skip DB write if tokens are null or equal
updateToken(context, federatedUser, federatedIdentityModel);
context.getIdp().updateBrokeredUser(session, realmModel, federatedUser, context);
Set<IdentityProviderMapperModel> mappers = realmModel.getIdentityProviderMappersByAlias(context.getIdpConfig().getAlias());
if (mappers != null) {
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
for (IdentityProviderMapperModel mapper : mappers) {
IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
IdentityProviderMapperSyncModeDelegate.delegateUpdateBrokeredUser(session, realmModel, federatedUser, mapper, context, target);
}
}
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
realmModel.getIdentityProviderMappersByAliasStream(context.getIdpConfig().getAlias()).forEach(mapper -> {
IdentityProviderMapper target = (IdentityProviderMapper) sessionFactory
.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
IdentityProviderMapperSyncModeDelegate.delegateUpdateBrokeredUser(session, realmModel, federatedUser, mapper, context, target);
});
}
private void setBasicUserAttributes(BrokeredIdentityContext context, UserModel federatedUser) {

Some files were not shown because too many files have changed in this diff Show more