Replace calls to deprecated RealmModel IDP methods

- use the new provider instead

Closes #31254

Signed-off-by: Stefan Guilhen <sguilhen@redhat.com>
This commit is contained in:
Stefan Guilhen 2024-08-01 13:11:24 -03:00 committed by Pedro Igor
parent 67b6cf7eac
commit aeb1951aba
38 changed files with 310 additions and 195 deletions

View file

@ -88,6 +88,8 @@ public class InfinispanIDPProvider implements IDPProvider {
@Override
public IdentityProviderModel getById(String internalId) {
if (internalId == null)
return null;
CachedIdentityProvider cached = realmCache.getCache().get(internalId, CachedIdentityProvider.class);
String realmId = getRealm().getId();
if (cached != null && !cached.getRealm().equals(realmId)) {
@ -130,6 +132,11 @@ public class InfinispanIDPProvider implements IDPProvider {
return cached.getIdentityProvider();
}
@Override
public Stream<String> getByFlow(String flowId, String search, Integer first, Integer max) {
return idpDelegate.getByFlow(flowId, search, first, max);
}
@Override
public Stream<IdentityProviderModel> getAllStream(String search, Integer first, Integer max) {
return idpDelegate.getAllStream(search, first, max);

View file

@ -28,10 +28,11 @@ import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaDelete;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.JoinType;
import jakarta.persistence.criteria.MapJoin;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.Session;
import org.jboss.logging.Logger;
import org.keycloak.broker.provider.IdentityProvider;
import org.keycloak.broker.provider.IdentityProviderFactory;
@ -46,6 +47,11 @@ import org.keycloak.models.jpa.entities.IdentityProviderEntity;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.utils.StringUtil;
import static org.keycloak.models.IdentityProviderModel.ALIAS;
import static org.keycloak.models.IdentityProviderModel.AUTHENTICATE_BY_DEFAULT;
import static org.keycloak.models.IdentityProviderModel.ENABLED;
import static org.keycloak.models.IdentityProviderModel.FIRST_BROKER_LOGIN_FLOW_ID;
import static org.keycloak.models.IdentityProviderModel.POST_BROKER_LOGIN_FLOW_ID;
import static org.keycloak.models.jpa.PaginationUtils.paginateQuery;
import static org.keycloak.utils.StreamsUtil.closing;
@ -203,21 +209,10 @@ public class JpaIDPProvider implements IDPProvider {
predicates.add(builder.equal(idp.get("realmId"), getRealm().getId()));
if (StringUtil.isNotBlank(search)) {
if (search.startsWith("\"") && search.endsWith("\"")) {
// exact search - alias must be an exact match
search = search.substring(1, search.length() - 1);
predicates.add(builder.equal(idp.get("alias"), search));
} else {
search = search.replace("%", "\\%").replace("_", "\\_").replace("*", "%");
if (!search.endsWith("%")) {
search += "%"; // default to prefix search
}
predicates.add(builder.like(builder.lower(idp.get("alias")), search.toLowerCase(), '\\'));
}
predicates.add(this.getAliasSearchPredicate(search, builder, idp));
}
query.orderBy(builder.asc(idp.get("alias")));
query.orderBy(builder.asc(idp.get(ALIAS)));
TypedQuery<IdentityProviderEntity> typedQuery = em.createQuery(query.select(idp).where(predicates.toArray(Predicate[]::new)));
return closing(paginateQuery(typedQuery, first, max).getResultStream()).map(this::toModel);
}
@ -233,21 +228,74 @@ public class JpaIDPProvider implements IDPProvider {
if (attrs != null) {
for (Map.Entry<String, String> entry : attrs.entrySet()) {
if (StringUtil.isBlank(entry.getKey())) {
String key = entry.getKey();
String value = entry.getValue();
if (StringUtil.isBlank(key)) {
continue;
}
Join<IdentityProviderEntity, Object> configJoin = idp.join("config", JoinType.LEFT);
predicates.add(builder.and(
builder.equal(configJoin.get("name"), entry.getKey()),
builder.equal(configJoin.get("value"), entry.getValue())));
switch(key) {
case ENABLED:
case AUTHENTICATE_BY_DEFAULT: {
predicates.add(builder.equal(idp.get(key), Boolean.valueOf(value)));
break;
} case FIRST_BROKER_LOGIN_FLOW_ID: {
if (StringUtils.isBlank(value)) {
predicates.add(builder.isNull(idp.get(key)));
} else {
predicates.add(builder.equal(idp.get(key), value));
}
break;
} default: {
String dbProductName = em.unwrap(Session.class).doReturningWork(connection -> connection.getMetaData().getDatabaseProductName());
MapJoin<IdentityProviderEntity, String, String> configJoin = idp.joinMap("config");
Predicate configNamePredicate = builder.equal(configJoin.key(), key);
if (dbProductName.equals("Oracle")) {
// SELECT * FROM identity_provider_config WHERE ... DBMS_LOB.COMPARE(value, '0') = 0 ...;
// Oracle is not able to compare a CLOB with a VARCHAR unless it being converted with TO_CHAR
// But for this all values in the table need to be smaller than 4K, otherwise the cast will fail with
// "ORA-22835: Buffer too small for CLOB to CHAR" (even if it is in another row).
// This leaves DBMS_LOB.COMPARE as the option to compare the CLOB with the value.
Predicate configValuePredicate = builder.equal(builder.function("DBMS_LOB.COMPARE", Integer.class, configJoin.value(), builder.literal(value)), 0);
predicates.add(builder.and(configNamePredicate, configValuePredicate));
} else {
predicates.add(builder.and(configNamePredicate, builder.equal(configJoin.value(), value)));
}
}
}
}
}
query.orderBy(builder.asc(idp.get("alias")));
query.orderBy(builder.asc(idp.get(ALIAS)));
TypedQuery<IdentityProviderEntity> typedQuery = em.createQuery(query.select(idp).where(predicates.toArray(Predicate[]::new)));
return closing(paginateQuery(typedQuery, first, max).getResultStream()).map(this::toModel);
}
@Override
public Stream<String> getByFlow(String flowId, String search, Integer first, Integer max) {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<String> query = builder.createQuery(String.class);
Root<IdentityProviderEntity> idp = query.from(IdentityProviderEntity.class);
List<Predicate> predicates = new ArrayList<>();
predicates.add(builder.equal(idp.get("realmId"), getRealm().getId()));
if (StringUtil.isNotBlank(flowId)) {
predicates.add(builder.or(
builder.equal(idp.get(FIRST_BROKER_LOGIN_FLOW_ID), flowId),
builder.equal(idp.get(POST_BROKER_LOGIN_FLOW_ID), flowId)
));
}
if (StringUtil.isNotBlank(search)) {
predicates.add(this.getAliasSearchPredicate(search, builder, idp));
}
query.orderBy(builder.asc(idp.get(ALIAS)));
TypedQuery<String> typedQuery = em.createQuery(query.select(idp.get(ALIAS)).where(predicates.toArray(Predicate[]::new)));
return closing(paginateQuery(typedQuery, first, max).getResultStream());
}
@Override
public long count() {
CriteriaBuilder builder = em.getCriteriaBuilder();
@ -263,6 +311,13 @@ public class JpaIDPProvider implements IDPProvider {
}
private IdentityProviderEntity getEntityById(String id, boolean failIfNotFound) {
if (id == null) {
if (failIfNotFound) {
throw new ModelException("Identity Provider with null internal id does not exist");
}
return null;
}
IdentityProviderEntity entity = em.find(IdentityProviderEntity.class, id);
if (entity == null) {
if (failIfNotFound) {
@ -284,7 +339,7 @@ public class JpaIDPProvider implements IDPProvider {
Root<IdentityProviderEntity> idp = query.from(IdentityProviderEntity.class);
Predicate predicate = builder.and(builder.equal(idp.get("realmId"), getRealm().getId()),
builder.equal(idp.get("alias"), alias));
builder.equal(idp.get(ALIAS), alias));
TypedQuery<IdentityProviderEntity> typedQuery = em.createQuery(query.select(idp).where(predicate));
try {
@ -294,6 +349,20 @@ public class JpaIDPProvider implements IDPProvider {
}
}
private Predicate getAliasSearchPredicate(String search, CriteriaBuilder builder, Root<IdentityProviderEntity> idp) {
if (search.startsWith("\"") && search.endsWith("\"")) {
// exact search - alias must be an exact match
search = search.substring(1, search.length() - 1);
return builder.equal(idp.get(ALIAS), search);
} else {
search = search.replace("%", "\\%").replace("_", "\\_").replace("*", "%");
if (!search.endsWith("%")) {
search += "%"; // default to prefix search
}
return builder.like(builder.lower(idp.get(ALIAS)), search.toLowerCase(), '\\');
}
}
private IdentityProviderModel toModel(IdentityProviderEntity entity) {
if (entity == null) {
return null;

View file

@ -1508,7 +1508,7 @@ public class RealmAdapter implements StorageProviderRealmModel, JpaModel<RealmEn
@Override
public void removeAuthenticationFlow(AuthenticationFlowModel model) {
if (KeycloakModelUtils.isFlowUsed(this, model)) {
if (KeycloakModelUtils.isFlowUsed(session,this, model)) {
throw new ModelException("Cannot remove authentication flow, it is currently in use");
}
AuthenticationFlowEntity entity = getAuthenticationFlowEntity(model.getId(), true);

View file

@ -333,7 +333,7 @@ public class JpaOrganizationProvider implements OrganizationProvider {
}
identityProvider.setOrganizationId(organizationEntity.getId());
getRealm().updateIdentityProvider(identityProvider);
session.identityProviders().update(identityProvider);
return true;
}
@ -345,7 +345,7 @@ public class JpaOrganizationProvider implements OrganizationProvider {
OrganizationEntity organizationEntity = getEntity(organization.getId());
return getRealm().getIdentityProvidersStream().filter(model -> organizationEntity.getId().equals(model.getOrganizationId()));
return session.identityProviders().getByOrganization(organizationEntity.getId(), null, null);
}
@Override
@ -362,7 +362,7 @@ public class JpaOrganizationProvider implements OrganizationProvider {
identityProvider.setOrganizationId(null);
identityProvider.getConfig().remove(ORGANIZATION_DOMAIN_ATTRIBUTE);
identityProvider.getConfig().remove(BROKER_PUBLIC);
getRealm().updateIdentityProvider(identityProvider);
session.identityProviders().update(identityProvider);
return true;
}
@ -510,9 +510,7 @@ public class JpaOrganizationProvider implements OrganizationProvider {
// return true only if the organization realm and the identity provider realm is the same
private boolean checkOrgIdpAndRealm(OrganizationEntity orgEntity, IdentityProviderModel idp) {
RealmModel orgRealm = session.realms().getRealm(orgEntity.getRealmId());
IdentityProviderModel orgIdpByAlias = orgRealm.getIdentityProviderByAlias(idp.getAlias());
IdentityProviderModel orgIdpByAlias = session.identityProviders().getByAlias(idp.getAlias());
return orgIdpByAlias != null && orgIdpByAlias.getInternalId().equals(idp.getInternalId());
}

View file

@ -195,7 +195,7 @@ public final class OrganizationAdapter implements OrganizationModel, JpaModel<Or
.filter(idp -> Objects.equals(domainEntity.getName(), idp.getConfig().get(ORGANIZATION_DOMAIN_ATTRIBUTE)))
.forEach(idp -> {
idp.getConfig().remove(ORGANIZATION_DOMAIN_ATTRIBUTE);
realm.updateIdentityProvider(idp);
session.identityProviders().update(idp);
});
}
}

View file

@ -17,10 +17,13 @@
package org.keycloak.migration.migrators;
import java.util.Map;
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;
@ -38,12 +41,20 @@ public class MigrateTo1_7_0 implements Migration {
}
public void migrate(KeycloakSession session) {
session.realms().getRealmsStream().forEach(realm -> migrateRealm(session, realm));
RealmModel sessionRealm = session.getContext().getRealm();
session.realms().getRealmsStream().forEach(realm -> {
session.getContext().setRealm(realm);
migrateRealm(session, realm);
});
session.getContext().setRealm(sessionRealm);
}
@Override
public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
RealmModel sessionRealm = session.getContext().getRealm();
session.getContext().setRealm(realm);
migrateRealm(session, realm);
session.getContext().setRealm(sessionRealm);
}
protected void migrateRealm(KeycloakSession session, RealmModel realm) {
@ -58,11 +69,10 @@ public class MigrateTo1_7_0 implements Migration {
DefaultAuthenticationFlows.migrateFlows(realm);
AuthenticationFlowModel firstBrokerLoginFlow = realm.getFlowByAlias(DefaultAuthenticationFlows.FIRST_BROKER_LOGIN_FLOW);
realm.getIdentityProvidersStream()
.filter(provider -> provider.getFirstBrokerLoginFlowId() == null)
.forEach(provider -> {
provider.setFirstBrokerLoginFlowId(firstBrokerLoginFlow.getId());
realm.updateIdentityProvider(provider);
session.identityProviders().getAllStream(Map.of(IdentityProviderModel.FIRST_BROKER_LOGIN_FLOW_ID, ""), null, null)
.forEach(provider -> {
provider.setFirstBrokerLoginFlowId(firstBrokerLoginFlow.getId());
session.identityProviders().update(provider);
});
}
}

View file

@ -17,6 +17,8 @@
package org.keycloak.migration.migrators;
import java.util.Map;
import org.jboss.logging.Logger;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.IdentityProviderModel;
@ -35,23 +37,27 @@ public class MigrateTo2_2_0 implements Migration {
}
public void migrate(KeycloakSession session) {
session.realms().getRealmsStream().forEach(this::addIdentityProviderAuthenticator);
RealmModel sessionRealm = session.getContext().getRealm();
session.realms().getRealmsStream().forEach(realm -> {
session.getContext().setRealm(realm);
addIdentityProviderAuthenticator(session, realm);
});
session.getContext().setRealm(sessionRealm);
}
@Override
public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
addIdentityProviderAuthenticator(realm);
RealmModel sessionRealm = session.getContext().getRealm();
session.getContext().setRealm(realm);
addIdentityProviderAuthenticator(session, realm);
session.getContext().setRealm(sessionRealm);
}
private void addIdentityProviderAuthenticator(RealmModel realm) {
String defaultProvider = realm.getIdentityProvidersStream()
.filter(IdentityProviderModel::isEnabled)
.filter(IdentityProviderModel::isAuthenticateByDefault)
private void addIdentityProviderAuthenticator(KeycloakSession session, RealmModel realm) {
String defaultProvider = session.identityProviders()
.getAllStream(Map.of(IdentityProviderModel.ENABLED, "true", IdentityProviderModel.AUTHENTICATE_BY_DEFAULT, "true"), 0, 1)
.map(IdentityProviderModel::getAlias)
.findFirst()
.orElse(null);
.findFirst().orElse(null);
DefaultAuthenticationFlows.addIdentityProviderAuthenticator(realm, defaultProvider);
}

View file

@ -556,7 +556,7 @@ public class DefaultExportImportManager implements ExportImportManager {
private static void importIdentityProviders(RealmRepresentation rep, RealmModel newRealm, KeycloakSession session) {
if (rep.getIdentityProviders() != null) {
for (IdentityProviderRepresentation representation : rep.getIdentityProviders()) {
newRealm.addIdentityProvider(RepresentationToModel.toModel(newRealm, representation, session));
session.identityProviders().create(RepresentationToModel.toModel(newRealm, representation, session));
}
}
}
@ -1595,7 +1595,7 @@ public class DefaultExportImportManager implements ExportImportManager {
org.setDomains(orgRep.getDomains().stream().map(r -> new OrganizationDomainModel(r.getName(), r.isVerified())).collect(Collectors.toSet()));
for (IdentityProviderRepresentation identityProvider : Optional.ofNullable(orgRep.getIdentityProviders()).orElse(Collections.emptyList())) {
IdentityProviderModel idp = newRealm.getIdentityProviderByAlias(identityProvider.getAlias());
IdentityProviderModel idp = session.identityProviders().getByAlias(identityProvider.getAlias());
provider.addIdentityProvider(org, idp);
}

View file

@ -64,7 +64,7 @@ public class AuthenticationManagementResource extends RoleMappingResource {
return realm.getAuthenticationFlowsStream()
.filter(flow -> flow.isTopLevel() && !Objects.equals(flow.getAlias(), DefaultAuthenticationFlows.SAML_ECP_FLOW))
.map(flow -> AuthenticationMapper.convertToModel(flow, realm))
.map(flow -> AuthenticationMapper.convertToModel(super.session, flow, realm))
.collect(Collectors.toList());
}
@ -88,11 +88,11 @@ public class AuthenticationManagementResource extends RoleMappingResource {
)
)}
)
public final List<String> listUsed(@PathParam("id") String id, @PathParam("type") String type, @QueryParam("first") @DefaultValue("0") long first,
@QueryParam("max") @DefaultValue("10") long max, @QueryParam("search") @DefaultValue("") String search) {
public final List<String> listUsed(@PathParam("id") String id, @PathParam("type") String type, @QueryParam("first") @DefaultValue("0") int first,
@QueryParam("max") @DefaultValue("10") int max, @QueryParam("search") @DefaultValue("") String search) {
auth.realm().requireViewAuthenticationFlows();
final AuthenticationFlowModel flow = realm.getAuthenticationFlowsStream().filter(f -> id.equals(f.getId())).collect(Collectors.toList()).get(0);
final AuthenticationFlowModel flow = realm.getAuthenticationFlowsStream().filter(f -> id.equals(f.getId())).toList().get(0);
if ("clients".equals(type)) {
final Stream<ClientModel> clients = realm.getClientsStream();
@ -105,11 +105,7 @@ public class AuthenticationManagementResource extends RoleMappingResource {
}
if ("idp".equals(type)) {
final Stream<IdentityProviderModel> identityProviders = realm.getIdentityProvidersStream();
return identityProviders.filter(idp -> flow.getId().equals(idp.getFirstBrokerLoginFlowId())
|| flow.getId().equals(idp.getPostBrokerLoginFlowId()))
.map(IdentityProviderModel::getAlias).filter(f -> f.contains(search))
.skip("".equals(search) ? first : 0).limit(max).collect(Collectors.toList());
return session.identityProviders().getByFlow(flow.getId(), search, first, max).toList();
}
throw new IllegalArgumentException("Invalid type");

View file

@ -8,14 +8,13 @@ import java.util.stream.Stream;
import org.keycloak.models.AuthenticationFlowModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
public class AuthenticationMapper {
private static final int MAX_USED_BY = 9;
public static Authentication convertToModel(AuthenticationFlowModel flow, RealmModel realm) {
final Stream<IdentityProviderModel> identityProviders = realm.getIdentityProvidersStream();
public static Authentication convertToModel(KeycloakSession session, AuthenticationFlowModel flow, RealmModel realm) {
final Authentication authentication = new Authentication();
authentication.setId(flow.getId());
@ -23,9 +22,7 @@ public class AuthenticationMapper {
authentication.setBuiltIn(flow.isBuiltIn());
authentication.setDescription(flow.getDescription());
final List<String> usedByIdp = identityProviders.filter(idp -> flow.getId().equals(idp.getFirstBrokerLoginFlowId())
|| flow.getId().equals(idp.getPostBrokerLoginFlowId()))
.map(IdentityProviderModel::getAlias).limit(MAX_USED_BY).collect(Collectors.toList());
final List<String> usedByIdp = session.identityProviders().getByFlow(flow.getId(), null,0, MAX_USED_BY).toList();
if (!usedByIdp.isEmpty()) {
authentication.setUsedBy(new UsedBy(UsedBy.UsedByType.SPECIFIC_PROVIDERS, usedByIdp));
}

View file

@ -909,7 +909,7 @@ public final class KeycloakModelUtils {
* @param model
* @return
*/
public static boolean isFlowUsed(RealmModel realm, AuthenticationFlowModel model) {
public static boolean isFlowUsed(KeycloakSession session, RealmModel realm, AuthenticationFlowModel model) {
AuthenticationFlowModel realmFlow = null;
if ((realmFlow = realm.getBrowserFlow()) != null && realmFlow.getId().equals(model.getId())) return true;
@ -931,9 +931,7 @@ public final class KeycloakModelUtils {
return true;
}
return realm.getIdentityProvidersStream().anyMatch(idp ->
Objects.equals(idp.getFirstBrokerLoginFlowId(), model.getId()) ||
Objects.equals(idp.getPostBrokerLoginFlowId(), model.getId()));
return session.identityProviders().getByFlow(model.getId(), null,0, 1).findAny().isPresent();
}
/**

View file

@ -504,7 +504,7 @@ public class ModelToRepresentation {
}
if (export) {
List<IdentityProviderRepresentation> identityProviders = realm.getIdentityProvidersStream()
List<IdentityProviderRepresentation> identityProviders = session.identityProviders().getAllStream()
.map(provider -> toRepresentation(realm, provider, export)).collect(Collectors.toList());
rep.setIdentityProviders(identityProviders);
List<IdentityProviderMapperRepresentation> identityProviderMappers = realm.getIdentityProviderMappersStream()

View file

@ -27,6 +27,7 @@ import java.util.ListIterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
@ -1643,9 +1644,8 @@ public class RepresentationToModel {
return;
}
IdentityProviderModel existing = realm.getIdentityProvidersStream()
.filter(p -> Objects.equals(p.getAlias(), representation.getAlias()) || Objects.equals(p.getInternalId(), representation.getInternalId()))
.findFirst().orElse(null);
IdentityProviderModel existing = Optional.ofNullable(session.identityProviders().getByAlias(representation.getAlias()))
.orElse(session.identityProviders().getById(representation.getInternalId()));
String orgId = existing == null ? representation.getConfig().get(OrganizationModel.ORGANIZATION_ATTRIBUTE) : existing.getOrganizationId();
if (orgId != null) {

View file

@ -132,6 +132,20 @@ public interface IDPProvider extends Provider {
return getAllStream(Map.of(OrganizationModel.ORGANIZATION_ATTRIBUTE, orgId), first, max);
}
/**
* Returns the aliases of all identity providers whose {@code firstBrokerLoginFlowId} or {@code postBrokerLoginFlowId}
* matches the provided {@code flowId}.
*
* @param flowId the id of the flow.
* @param search an optional {@link String} representing an identity provider alias (partial or exact). If the value is enclosed
* in double quotes, the method treats it as an exact search (e.g. {@code "name"}). If the value is enclosed in
* wildcards, the method treats it as an infix search (e.g. {@code *name*}). Otherwise, the method treats it as a
* prefix search (i.e. {@code name*} and {@code name} return the same results).
* @param first the position of the first result to be processed (pagination offset). Ignored if negative or {@code null}.
* @param max the maximum number of results to be returned. Ignored if negative or {@code null}.
* @return a non-null stream of {@link IdentityProviderModel}s that match the search criteria.
*/
Stream<String> getByFlow(String flowId, String search, Integer first, Integer max);
/**
* Returns the number of IDPs in the realm.

View file

@ -31,20 +31,22 @@ import java.util.Objects;
*/
public class IdentityProviderModel implements Serializable {
public static final String ALIAS = "alias";
public static final String ALLOWED_CLOCK_SKEW = "allowedClockSkew";
public static final String LOGIN_HINT = "loginHint";
public static final String PASS_MAX_AGE = "passMaxAge";
public static final String SYNC_MODE = "syncMode";
public static final String HIDE_ON_LOGIN = "hideOnLoginPage";
public static final String FILTERED_BY_CLAIMS = "filteredByClaim";
public static final String AUTHENTICATE_BY_DEFAULT = "authenticateByDefault";
public static final String CASE_SENSITIVE_ORIGINAL_USERNAME = "caseSensitiveOriginalUsername";
public static final String CLAIM_FILTER_NAME = "claimFilterName";
public static final String CLAIM_FILTER_VALUE = "claimFilterValue";
public static final String DO_NOT_STORE_USERS = "doNotStoreUsers";
public static final String ENABLED = "enabled";
public static final String FILTERED_BY_CLAIMS = "filteredByClaim";
public static final String FIRST_BROKER_LOGIN_FLOW_ID = "firstBrokerLoginFlowId";
public static final String HIDE_ON_LOGIN = "hideOnLoginPage";
public static final String LOGIN_HINT = "loginHint";
public static final String METADATA_DESCRIPTOR_URL = "metadataDescriptorUrl";
public static final String CASE_SENSITIVE_ORIGINAL_USERNAME = "caseSensitiveOriginalUsername";
public static final String PASS_MAX_AGE = "passMaxAge";
public static final String POST_BROKER_LOGIN_FLOW_ID = "postBrokerLoginFlowId";
public static final String SYNC_MODE = "syncMode";
private String internalId;
@ -60,7 +62,7 @@ public class IdentityProviderModel implements Serializable {
private String providerId;
private boolean enabled;
private boolean trustEmail;
private boolean storeToken;
@ -232,14 +234,14 @@ public class IdentityProviderModel implements Serializable {
/**
* <p>Validates this configuration.
*
*
* <p>Sub-classes can override this method in order to enforce provider specific validations.
*
*
* @param realm the realm
*/
public void validate(RealmModel realm) {
}
public IdentityProviderSyncMode getSyncMode() {
return IdentityProviderSyncMode.valueOf(getConfig().getOrDefault(SYNC_MODE, "LEGACY"));
}
@ -264,7 +266,7 @@ public class IdentityProviderModel implements Serializable {
getConfig().put(PASS_MAX_AGE, String.valueOf(passMaxAge));
}
public boolean isHideOnLogin() {
return Boolean.valueOf(getConfig().get(HIDE_ON_LOGIN));
}

View file

@ -72,7 +72,7 @@ public class SerializedBrokeredIdentityContext implements UpdateProfileContext {
public UserProfileContext getUserProfileContext() {
return UserProfileContext.IDP_REVIEW;
}
public String getId() {
return id;
}
@ -265,7 +265,7 @@ public class SerializedBrokeredIdentityContext implements UpdateProfileContext {
public BrokeredIdentityContext deserialize(KeycloakSession session, AuthenticationSessionModel authSession) {
RealmModel realm = authSession.getRealm();
IdentityProviderModel idpConfig = realm.getIdentityProviderByAlias(getIdentityProviderId());
IdentityProviderModel idpConfig = session.identityProviders().getByAlias(getIdentityProviderId());
if (idpConfig == null) {
throw new ModelException("Can't find identity provider with ID " + getIdentityProviderId() + " in realm " + realm.getName());
@ -282,7 +282,7 @@ public class SerializedBrokeredIdentityContext implements UpdateProfileContext {
ctx.setBrokerUserId(getBrokerUserId());
ctx.setToken(getToken());
IdentityProvider idp = IdentityBrokerService.getIdentityProvider(session, realm, idpConfig.getAlias());
IdentityProvider idp = IdentityBrokerService.getIdentityProvider(session, idpConfig.getAlias());
ctx.setIdp(idp);
IdentityProviderDataMarshaller serializer = idp.getMarshaller();

View file

@ -79,11 +79,8 @@ public class IdentityProviderAuthenticator implements Authenticator {
}
protected void redirect(AuthenticationFlowContext context, String providerId, String loginHint) {
Optional<IdentityProviderModel> idp = context.getRealm().getIdentityProvidersStream()
.filter(IdentityProviderModel::isEnabled)
.filter(identityProvider -> Objects.equals(providerId, identityProvider.getAlias()))
.findFirst();
if (idp.isPresent()) {
IdentityProviderModel idp = context.getSession().identityProviders().getByAlias(providerId);
if (idp != null && idp.isEnabled()) {
String accessCode = new ClientSessionCode<>(context.getSession(), context.getRealm(), context.getAuthenticationSession()).getOrGenerateCode();
String clientId = context.getAuthenticationSession().getClient().getClientId();
String tabId = context.getAuthenticationSession().getTabId();
@ -93,7 +90,7 @@ public class IdentityProviderAuthenticator implements Authenticator {
.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))) {
Boolean.parseBoolean(idp.getConfig().get(ACCEPTS_PROMPT_NONE))) {
context.getAuthenticationSession().setAuthNote(AuthenticationProcessor.FORWARDED_PASSIVE_LOGIN, "true");
}
LOG.debugf("Redirecting to %s", providerId);

View file

@ -51,12 +51,12 @@ public class LoginFormsUtil {
// If the current user is not null, then it's a re-auth, and we should filter the possible options with the pre-14173 logic
// If the current user is null, then it's one of the following cases:
// - either connecting a new IdP to the user's account.
// - in this case the currentUser is null AND the current flow is the FIRST_BROKER_LOGIN_PATH
// - so we should filter out the one they just used for login, as they need to re-auth themself with an already linked IdP account
// - in this case the currentUser is null AND the current flow is the FIRST_BROKER_LOGIN_PATH
// - so we should filter out the one they just used for login, as they need to re-auth themselves with an already linked IdP account
// - or we're on the Login page
// - in this case the current user is null AND the current flow is NOT the FIRST_BROKER_LOGIN_PATH
// - so we should show all the possible IdPs to the user trying to log in (this is the bug in #14173)
// - so we're skipping this branch, and retunring everything at the end of the method
// - in this case the current user is null AND the current flow is NOT the FIRST_BROKER_LOGIN_PATH
// - so we should show all the possible IdPs to the user trying to log in (this is the bug in #14173)
// - so we're skipping this branch, and returning everything at the end of the method
if (currentUser != null || Objects.equals(LoginActionsService.FIRST_BROKER_LOGIN_PATH, currentFlowPath)) {
return filterIdentityProviders(providers, session, context);
}

View file

@ -53,6 +53,7 @@ import org.keycloak.services.resources.admin.AdminEventBuilder;
public class OrganizationIdentityProvidersResource {
private final RealmModel realm;
private final KeycloakSession session;
private final OrganizationProvider organizationProvider;
private final OrganizationModel organization;
@ -63,6 +64,7 @@ public class OrganizationIdentityProvidersResource {
public OrganizationIdentityProvidersResource(KeycloakSession session, OrganizationModel organization, AdminEventBuilder adminEvent) {
this.realm = session == null ? null : session.getContext().getRealm();
this.session = session;
this.organizationProvider = session == null ? null : session.getProvider(OrganizationProvider.class);
this.organization = organization;
}
@ -75,9 +77,7 @@ public class OrganizationIdentityProvidersResource {
"or if it is already associated with the organization, an error response is returned")
public Response addIdentityProvider(String id) {
try {
IdentityProviderModel identityProvider = this.realm.getIdentityProvidersStream()
.filter(p -> Objects.equals(p.getAlias(), id) || Objects.equals(p.getInternalId(), id))
.findFirst().orElse(null);
IdentityProviderModel identityProvider = session.identityProviders().getByIdOrAlias(id);
if (identityProvider == null) {
throw ErrorResponse.error("Identity provider not found with the given alias", Status.BAD_REQUEST);
@ -111,7 +111,7 @@ public class OrganizationIdentityProvidersResource {
description = "Searches for an identity provider with the given alias. If one is found and is associated with the " +
"organization, it is returned. Otherwise, an error response with status NOT_FOUND is returned")
public IdentityProviderRepresentation getIdentityProvider(@PathParam("alias") String alias) {
IdentityProviderModel broker = realm.getIdentityProviderByAlias(alias);
IdentityProviderModel broker = session.identityProviders().getByAlias(alias);
if (!isOrganizationBroker(broker)) {
throw ErrorResponse.error("Identity provider not associated with the organization", Status.NOT_FOUND);
@ -128,7 +128,7 @@ public class OrganizationIdentityProvidersResource {
description = "Breaks the association between the identity provider and the organization. The provider itself is not deleted. " +
"If no provider is found, or if it is not currently associated with the org, an error response is returned")
public Response delete(@PathParam("alias") String alias) {
IdentityProviderModel broker = realm.getIdentityProviderByAlias(alias);
IdentityProviderModel broker = session.identityProviders().getByAlias(alias);
if (!isOrganizationBroker(broker)) {
throw ErrorResponse.error("Identity provider not found with the given alias", Status.NOT_FOUND);

View file

@ -68,8 +68,7 @@ public class OrganizationAwareIdentityProviderBean extends IdentityProviderBean
}
private boolean isPublicOrganizationBroker(IdentityProvider idp) {
RealmModel realm = session.getContext().getRealm();
IdentityProviderModel model = realm.getIdentityProviderByAlias(idp.getAlias());
IdentityProviderModel model = session.identityProviders().getByAlias(idp.getAlias());
if (model.getOrganizationId() == null) {
return false;
@ -85,9 +84,7 @@ public class OrganizationAwareIdentityProviderBean extends IdentityProviderBean
}
private boolean isRealmBroker(IdentityProvider idp) {
RealmModel realm = session.getContext().getRealm();
IdentityProviderModel model = realm.getIdentityProviderByAlias(idp.getAlias());
IdentityProviderModel model = session.identityProviders().getByAlias(idp.getAlias());
return model.getOrganizationId() == null;
}
}

View file

@ -94,7 +94,7 @@ public class Organizations {
List<IdentityProviderModel> organizationBrokers = organization.getIdentityProviders().toList();
session.users().getFederatedIdentitiesStream(realm, user)
.map(f -> {
IdentityProviderModel broker = realm.getIdentityProviderByAlias(f.getIdentityProvider());
IdentityProviderModel broker = session.identityProviders().getByAlias(f.getIdentityProvider());
if (!organizationBrokers.contains(broker)) {
return null;

View file

@ -46,12 +46,12 @@ public class IdentityProvidersPartialImport extends AbstractPartialImport<Identi
@Override
public String getModelId(RealmModel realm, KeycloakSession session, IdentityProviderRepresentation idpRep) {
return realm.getIdentityProviderByAlias(getName(idpRep)).getInternalId();
return session.identityProviders().getByAlias(getName(idpRep)).getInternalId();
}
@Override
public boolean exists(RealmModel realm, KeycloakSession session, IdentityProviderRepresentation idpRep) {
return realm.getIdentityProviderByAlias(getName(idpRep)) != null;
return session.identityProviders().getByAlias(getName(idpRep)) != null;
}
@Override
@ -66,14 +66,13 @@ public class IdentityProvidersPartialImport extends AbstractPartialImport<Identi
@Override
public void remove(RealmModel realm, KeycloakSession session, IdentityProviderRepresentation idpRep) {
realm.removeIdentityProviderByAlias(getName(idpRep));
session.identityProviders().remove(getName(idpRep));
}
@Override
public void create(RealmModel realm, KeycloakSession session, IdentityProviderRepresentation idpRep) {
idpRep.setInternalId(KeycloakModelUtils.generateId());
IdentityProviderModel identityProvider = RepresentationToModel.toModel(realm, idpRep, session);
realm.addIdentityProvider(identityProvider);
session.identityProviders().create(RepresentationToModel.toModel(realm, idpRep, session));
}
}

View file

@ -260,14 +260,14 @@ public class DefaultTokenExchangeProvider implements TokenExchangeProvider {
protected Response exchangeToIdentityProvider(UserModel targetUser, UserSessionModel targetUserSession, String requestedIssuer) {
event.detail(Details.REQUESTED_ISSUER, requestedIssuer);
IdentityProviderModel providerModel = realm.getIdentityProviderByAlias(requestedIssuer);
IdentityProviderModel providerModel = session.identityProviders().getByAlias(requestedIssuer);
if (providerModel == null) {
event.detail(Details.REASON, "unknown requested_issuer");
event.error(Errors.UNKNOWN_IDENTITY_PROVIDER);
throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "Invalid issuer", Response.Status.BAD_REQUEST);
}
IdentityProvider provider = IdentityBrokerService.getIdentityProvider(session, realm, requestedIssuer);
IdentityProvider<?> provider = IdentityBrokerService.getIdentityProvider(session, requestedIssuer);
if (!(provider instanceof ExchangeTokenToIdentityProviderToken)) {
event.detail(Details.REASON, "exchange unsupported by requested_issuer");
event.error(Errors.UNKNOWN_IDENTITY_PROVIDER);
@ -518,20 +518,26 @@ public class DefaultTokenExchangeProvider implements TokenExchangeProvider {
AtomicReference<ExchangeExternalToken> externalIdp = new AtomicReference<>(null);
AtomicReference<IdentityProviderModel> externalIdpModel = new AtomicReference<>(null);
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.set(external);
externalIdpModel.set(idpModel);
return true;
}
}
return false;
}).findFirst();
// try to find the IDP whose alias matches the issuer or the subject issuer in the form params.
this.locateExchangeExternalTokenByAlias(issuer, externalIdp, externalIdpModel);
if (externalIdp.get() == null && formParams.getFirst(OAuth2Constants.SUBJECT_ISSUER) != null) {
this.locateExchangeExternalTokenByAlias(formParams.getFirst(OAuth2Constants.SUBJECT_ISSUER), externalIdp, externalIdpModel);
}
if (externalIdp.get() == null) { // searching by alias didn't work, search all IDPs using ExchangeExternalToken.isIssuer to find a match
session.identityProviders().getAllStream().filter(idpModel -> {
IdentityProvider idp = IdentityBrokerService.getIdentityProviderFactory(session, idpModel).create(session, idpModel);
if (idp instanceof ExchangeExternalToken) {
ExchangeExternalToken external = (ExchangeExternalToken) idp;
if (external.isIssuer(issuer, formParams)) {
externalIdp.set(external);
externalIdpModel.set(idpModel);
return true;
}
}
return false;
}).findFirst();
}
if (externalIdp.get() == null) {
event.error(Errors.INVALID_ISSUER);
@ -687,4 +693,15 @@ public class DefaultTokenExchangeProvider implements TokenExchangeProvider {
}
}
private void locateExchangeExternalTokenByAlias(String alias, AtomicReference<ExchangeExternalToken> externalIdp,
AtomicReference<IdentityProviderModel> externalIdpModel) {
IdentityProviderModel idpModel = session.identityProviders().getByAlias(alias);
IdentityProvider idp = IdentityBrokerService.getIdentityProviderFactory(session, idpModel).create(session, idpModel);
if (idp instanceof ExchangeExternalToken) {
externalIdp.set((ExchangeExternalToken) idp);
externalIdpModel.set(idpModel);
}
}
}

View file

@ -1505,7 +1505,7 @@ public class TokenManager {
private Stream<OIDCIdentityProvider> getOIDCIdentityProviders(RealmModel realm, KeycloakSession session) {
try {
return realm.getIdentityProvidersStream()
return session.identityProviders().getAllStream()
.map(idpModel ->
IdentityBrokerService.getIdentityProviderFactory(session, idpModel).create(session, idpModel))
.filter(OIDCIdentityProvider.class::isInstance)

View file

@ -417,7 +417,7 @@ public class AuthenticationManager {
if (logoutBroker) {
String brokerId = userSession.getNote(Details.IDENTITY_PROVIDER);
if (brokerId != null) {
IdentityProvider identityProvider = IdentityBrokerService.getIdentityProvider(session, realm, brokerId);
IdentityProvider identityProvider = IdentityBrokerService.getIdentityProvider(session, brokerId);
try {
identityProvider.backchannelLogout(session, userSession, uriInfo, realm);
} catch (Exception e) {
@ -648,7 +648,7 @@ public class AuthenticationManager {
String brokerId = userSession.getNote(Details.IDENTITY_PROVIDER);
String initiatingIdp = logoutAuthSession.getAuthNote(AuthenticationManager.LOGOUT_INITIATING_IDP);
if (brokerId != null && !brokerId.equals(initiatingIdp)) {
IdentityProvider identityProvider = IdentityBrokerService.getIdentityProvider(session, realm, brokerId);
IdentityProvider identityProvider = IdentityBrokerService.getIdentityProvider(session, brokerId);
Response response = identityProvider.keycloakInitiatedBrowserLogout(session, userSession, uriInfo, realm);
if (response != null) {
return response;

View file

@ -293,7 +293,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
}
IdentityProviderModel identityProviderModel = realmModel.getIdentityProviderByAlias(providerAlias);
IdentityProviderModel identityProviderModel = session.identityProviders().getByAlias(providerAlias);
if (identityProviderModel == null) {
event.error(Errors.UNKNOWN_IDENTITY_PROVIDER);
UriBuilder builder = UriBuilder.fromUri(redirectUri)
@ -330,7 +330,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
event.success();
try {
IdentityProvider<?> identityProvider = getIdentityProvider(session, realmModel, providerAlias);
IdentityProvider<?> identityProvider = getIdentityProvider(session, providerAlias);
Response response = identityProvider.performLogin(createAuthenticationRequest(identityProvider, providerAlias, clientSessionCode));
if (response != null) {
@ -381,14 +381,14 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
ClientSessionCode<AuthenticationSessionModel> clientSessionCode = new ClientSessionCode<>(session, realmModel, authSession);
clientSessionCode.setAction(AuthenticationSessionModel.Action.AUTHENTICATE.name());
IdentityProviderModel identityProviderModel = realmModel.getIdentityProviderByAlias(providerAlias);
IdentityProviderModel identityProviderModel = session.identityProviders().getByAlias(providerAlias);
if (identityProviderModel == null) {
throw new IdentityBrokerException("Identity Provider [" + providerAlias + "] not found.");
}
if (identityProviderModel.isLinkOnly()) {
throw new IdentityBrokerException("Identity Provider [" + providerAlias + "] is not allowed to perform a login.");
}
if (clientSessionCode != null && clientSessionCode.getClientSession() != null && loginHint != null) {
if (clientSessionCode.getClientSession() != null && loginHint != null) {
clientSessionCode.getClientSession().setClientNote(OIDCLoginProtocol.LOGIN_HINT_PARAM, loginHint);
}
@ -437,7 +437,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
IdentityProvider identityProvider;
try {
identityProvider = getIdentityProvider(session, realmModel, providerAlias);
identityProvider = getIdentityProvider(session, providerAlias);
} catch (IdentityBrokerException e) {
throw new NotFoundException(e.getMessage());
}
@ -490,7 +490,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
}
IdentityProvider identityProvider = getIdentityProvider(session, realmModel, providerAlias);
IdentityProvider identityProvider = getIdentityProvider(session, providerAlias);
IdentityProviderModel identityProviderConfig = getIdentityProviderConfig(providerAlias);
if (identityProviderConfig.isStoreToken()) {
@ -1247,7 +1247,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
fireErrorEvent(message, throwable);
if (throwable != null && throwable instanceof WebApplicationException) {
if (throwable instanceof WebApplicationException) {
WebApplicationException webEx = (WebApplicationException) throwable;
return webEx.getResponse();
}
@ -1312,8 +1312,8 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
throw ErrorResponse.error(message, Response.Status.NOT_FOUND);
}
public static IdentityProvider<?> getIdentityProvider(KeycloakSession session, RealmModel realm, String alias) {
IdentityProviderModel identityProviderModel = realm.getIdentityProviderByAlias(alias);
public static IdentityProvider<?> getIdentityProvider(KeycloakSession session, String alias) {
IdentityProviderModel identityProviderModel = session.identityProviders().getByAlias(alias);
if (identityProviderModel != null) {
IdentityProviderFactory<?> providerFactory = getIdentityProviderFactory(session, identityProviderModel);
@ -1338,7 +1338,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
}
private IdentityProviderModel getIdentityProviderConfig(String providerAlias) {
IdentityProviderModel model = this.realmModel.getIdentityProviderByAlias(providerAlias);
IdentityProviderModel model = session.identityProviders().getByAlias(providerAlias);
if (model == null) {
throw new IdentityBrokerException("Configuration for identity provider [" + providerAlias + "] not found.");
}

View file

@ -20,6 +20,7 @@ import java.io.IOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.SortedSet;
@ -113,7 +114,7 @@ public class LinkedAccountsResource {
public SortedSet<LinkedAccountRepresentation> getLinkedAccounts(KeycloakSession session, RealmModel realm, UserModel user) {
Set<String> socialIds = findSocialIds();
return realm.getIdentityProvidersStream().filter(IdentityProviderModel::isEnabled)
return session.identityProviders().getAllStream(Map.of(IdentityProviderModel.ENABLED, "true"), null, null)
.map(provider -> toLinkedAccountRepresentation(provider, socialIds, session.users().getFederatedIdentitiesStream(realm, user)))
.collect(Collectors.toCollection(TreeSet::new));
}
@ -266,6 +267,6 @@ public class LinkedAccountsResource {
}
private boolean isValidProvider(String providerAlias) {
return realm.getIdentityProvidersStream().anyMatch(model -> Objects.equals(model.getAlias(), providerAlias));
return session.identityProviders().getByAlias(providerAlias) != null;
}
}

View file

@ -65,10 +65,11 @@ import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -134,7 +135,7 @@ public class IdentityProviderResource {
String alias = this.identityProviderModel.getAlias();
session.users().preRemove(realm, identityProviderModel);
this.realm.removeIdentityProviderByAlias(alias);
session.identityProviders().remove(alias);
realm.getIdentityProviderMappersByAliasStream(alias)
.collect(Collectors.toList()).forEach(realm::removeIdentityProviderMapper);
@ -182,12 +183,11 @@ public class IdentityProviderResource {
}
private void updateIdpFromRep(IdentityProviderRepresentation providerRep, RealmModel realm, KeycloakSession session) {
String internalId = providerRep.getInternalId();
String newProviderId = providerRep.getAlias();
String oldProviderId = getProviderIdByInternalId(realm, internalId);
String newProviderAlias = providerRep.getAlias();
String oldProviderAlias = getAliasByInternalId(providerRep.getInternalId());
if (oldProviderId == null) {
lookUpProviderIdByAlias(realm, providerRep);
if (oldProviderAlias == null) {
providerRep.setInternalId(getInternalIdByAlias(providerRep.getAlias()));
}
IdentityProviderModel updated = RepresentationToModel.toModel(realm, providerRep, session);
@ -196,34 +196,44 @@ public class IdentityProviderResource {
updated.getConfig().put("clientSecret", identityProviderModel.getConfig() != null ? identityProviderModel.getConfig().get("clientSecret") : null);
}
realm.updateIdentityProvider(updated);
session.identityProviders().update(updated);
if (oldProviderId != null && !oldProviderId.equals(newProviderId)) {
if (oldProviderAlias != null && !oldProviderAlias.equals(newProviderAlias)) {
// Admin changed the ID (alias) of identity provider. We must update all clients and users
logger.debug("Changing providerId in all clients and linked users. oldProviderId=" + oldProviderId + ", newProviderId=" + newProviderId);
logger.debug("Changing providerId in all clients and linked users. oldProviderId=" + oldProviderAlias + ", newProviderId=" + newProviderAlias);
updateUsersAfterProviderAliasChange(session.users().searchForUserStream(realm, Collections.singletonMap(UserModel.INCLUDE_SERVICE_ACCOUNT, Boolean.FALSE.toString())),
oldProviderId, newProviderId, realm, session);
oldProviderAlias, newProviderAlias, realm, session);
}
}
// return ID of IdentityProvider from realm based on internalId of this provider
private static String getProviderIdByInternalId(RealmModel realm, String providerInternalId) {
return realm.getIdentityProvidersStream().filter(p -> Objects.equals(p.getInternalId(), providerInternalId))
.map(IdentityProviderModel::getAlias)
.findFirst()
.orElse(null);
/**
* Returns the alias of the IDP whose internal ID matches the specified ID.
*
* @param providerInternalId the IDP's internal ID.
* @return the provider's alias, if an IDP is located with the given ID; {@code null} otherwise.
*/
private String getAliasByInternalId(String providerInternalId) {
IdentityProviderModel identityProviderModel = session.identityProviders().getById(providerInternalId);
return identityProviderModel != null ? identityProviderModel.getAlias() : null;
}
// sets internalId to IdentityProvider based on alias
private static void lookUpProviderIdByAlias(RealmModel realm, IdentityProviderRepresentation providerRep) {
IdentityProviderModel identityProviderModel = realm.getIdentityProvidersStream()
.filter(p -> Objects.equals(p.getAlias(), providerRep.getAlias()))
.findFirst()
.orElseThrow(NotFoundException::new);
providerRep.setInternalId(identityProviderModel.getInternalId());
/**
* Returns the internal ID of the IDP whose alias matches the specified alias.
*
* @param alias the IDP's alias.
* @return the provider's internal ID.
* @throws NotFoundException if an IDP with a matching alias is not found.
*/
private String getInternalIdByAlias(String alias) {
if (alias != null) {
IdentityProviderModel identityProviderModel = session.identityProviders().getByAlias(alias);
if (identityProviderModel != null) {
return identityProviderModel.getInternalId();
}
}
throw new NotFoundException("Identity provider not found with alias: " + alias);
}
private static void updateUsersAfterProviderAliasChange(Stream<UserModel> users, String oldProviderId, String newProviderId, RealmModel realm, KeycloakSession session) {

View file

@ -212,7 +212,7 @@ public class IdentityProvidersResource {
try {
IdentityProviderModel identityProvider = RepresentationToModel.toModel(realm, representation, session);
this.realm.addIdentityProvider(identityProvider);
session.identityProviders().create(identityProvider);
representation.setInternalId(identityProvider.getInternalId());
adminEvent.operation(OperationType.CREATE).resourcePath(session.getContext().getUri(), identityProvider.getAlias())
@ -235,14 +235,12 @@ public class IdentityProvidersResource {
@Path("instances/{alias}")
public IdentityProviderResource getIdentityProvider(@PathParam("alias") String alias) {
this.auth.realm().requireViewIdentityProviders();
IdentityProviderModel identityProviderModel = this.realm.getIdentityProvidersStream()
.filter(p -> Objects.equals(p.getAlias(), alias) || Objects.equals(p.getInternalId(), alias))
.findFirst().orElse(null);
IdentityProviderModel identityProviderModel = session.identityProviders().getByIdOrAlias(alias);
return new IdentityProviderResource(this.auth, realm, session, identityProviderModel, adminEvent);
}
private IdentityProviderFactory getProviderFactoryById(String providerId) {
private IdentityProviderFactory<?> getProviderFactoryById(String providerId) {
return getProviderFactories()
.filter(providerFactory -> Objects.equals(providerId, providerFactory.getId()))
.map(IdentityProviderFactory.class::cast)

View file

@ -468,9 +468,8 @@ public class UserResource {
}
private Stream<FederatedIdentityRepresentation> getFederatedIdentities(UserModel user) {
Set<String> idps = realm.getIdentityProvidersStream().map(IdentityProviderModel::getAlias).collect(Collectors.toSet());
return session.users().getFederatedIdentitiesStream(realm, user)
.filter(identity -> idps.contains(identity.getIdentityProvider()))
.filter(identity -> session.identityProviders().getByAlias(identity.getIdentityProvider()) != null)
.map(ModelToRepresentation::toRepresentation);
}

View file

@ -730,7 +730,7 @@ public class TestingResourceProvider implements RealmResourceProvider {
@Path("/identity-config")
@Produces(MediaType.APPLICATION_JSON)
public Map<String, String> getIdentityProviderConfig(@QueryParam("alias") String alias) {
return session.getContext().getRealm().getIdentityProviderByAlias(alias).getConfig();
return session.identityProviders().getByAlias(alias).getConfig();
}
@PUT

View file

@ -60,9 +60,9 @@ final class BrokerRunOnServerUtil {
execution.setAuthenticatorFlow(false);
realm.addAuthenticatorExecution(execution);
IdentityProviderModel idp = realm.getIdentityProviderByAlias(idpAlias);
IdentityProviderModel idp = session.identityProviders().getByAlias(idpAlias);
idp.setPostBrokerLoginFlowId(postBrokerFlow.getId());
realm.updateIdentityProvider(idp);
session.identityProviders().update(idp);
};
}
@ -70,9 +70,9 @@ final class BrokerRunOnServerUtil {
return session -> {
RealmModel realm = session.getContext().getRealm();
IdentityProviderModel idp = realm.getIdentityProviderByAlias(idpAlias);
IdentityProviderModel idp = session.identityProviders().getByAlias(idpAlias);
idp.setPostBrokerLoginFlowId(null);
realm.updateIdentityProvider(idp);
session.identityProviders().update(idp);
};
}
@ -123,9 +123,9 @@ final class BrokerRunOnServerUtil {
execution2.setParentFlow(newFlow.getId());
execution2 = appRealm.addAuthenticatorExecution(execution2);
IdentityProviderModel idp = appRealm.getIdentityProviderByAlias(idpAlias);
IdentityProviderModel idp = session.identityProviders().getByAlias(idpAlias);
idp.setFirstBrokerLoginFlowId(newFlow.getId());
appRealm.updateIdentityProvider(idp);
session.identityProviders().update(idp);
});
}
@ -165,9 +165,9 @@ final class BrokerRunOnServerUtil {
execution.setParentFlow(newFlow.getId());
appRealm.addAuthenticatorExecution(execution);
IdentityProviderModel idp = appRealm.getIdentityProviderByAlias(idpAlias);
IdentityProviderModel idp = session.identityProviders().getByAlias(idpAlias);
idp.setFirstBrokerLoginFlowId(newFlow.getId());
appRealm.updateIdentityProvider(idp);
session.identityProviders().update(idp);
};
}

View file

@ -190,7 +190,7 @@ public final class KcOidcBrokerTokenExchangeTest extends AbstractInitializedBase
private static void setupRealm(KeycloakSession session) {
RealmModel realm = session.getContext().getRealm();
IdentityProviderModel idp = realm.getIdentityProviderByAlias(IDP_OIDC_ALIAS);
IdentityProviderModel idp = session.identityProviders().getByAlias(IDP_OIDC_ALIAS);
org.junit.Assert.assertNotNull(idp);
ClientModel client = realm.addClient("test-app");

View file

@ -240,7 +240,7 @@ public class SocialLoginTest extends AbstractKeycloakTest {
Policy clientPolicy = management.authz().getStoreFactory().getPolicyStore().create(server, clientPolicyRep);
management.users().adminImpersonatingPermission().addAssociatedPolicy(clientPolicy);
management.users().adminImpersonatingPermission().setDecisionStrategy(DecisionStrategy.AFFIRMATIVE);
realm.getIdentityProvidersStream().forEach(idp -> {
session.identityProviders().getAllStream().forEach(idp -> {
management.idps().setPermissionsEnabled(idp, true);
management.idps().exchangeToPermission(idp).addAssociatedPolicy(clientPolicy);
});

View file

@ -252,7 +252,7 @@ public class OrganizationIdentityProviderTest extends AbstractOrganizationTest {
RealmModel realm = session.realms().getRealmByName("master");
RealmModel current = session.getContext().getRealm();
session.getContext().setRealm(realm);
IdentityProviderModel idp = realm.getIdentityProviderByAlias("master-identity-provider");
IdentityProviderModel idp = session.identityProviders().getByAlias("master-identity-provider");
// restore the context and try to add the idp.
session.getContext().setRealm(current);

View file

@ -56,9 +56,9 @@ public abstract class AbstractUserSessionLimitsBrokerTest extends AbstractInitia
configureSessionLimits(realm, postBrokerFlow, behavior, realmLimit, clientLimit);
IdentityProviderModel idp = realm.getIdentityProviderByAlias(idpAlias);
IdentityProviderModel idp = session.identityProviders().getByAlias(idpAlias);
idp.setPostBrokerLoginFlowId(postBrokerFlow.getId());
realm.updateIdentityProvider(idp);
session.identityProviders().update(idp);
});
}

View file

@ -203,9 +203,9 @@ public class FlowUtil {
public FlowUtil usesInIdentityProvider(String idpAlias) {
// Setup new FirstBrokerLogin flow to identity provider
IdentityProviderModel idp = realm.getIdentityProviderByAlias(idpAlias);
IdentityProviderModel idp = session.identityProviders().getByAlias(idpAlias);
idp.setFirstBrokerLoginFlowId(currentFlow.getId());
realm.updateIdentityProvider(idp);
session.identityProviders().update(idp);
return this;
}
@ -329,4 +329,4 @@ public class FlowUtil {
setFlow.accept(realm.getFlowByAlias(defaultFlowAlias));
}
}
}
}

View file

@ -58,7 +58,7 @@ public class FederatedIdentityModelTest extends KeycloakModelTest {
IdentityProviderModel identityProviderModel = identityProviderFactory.createConfig();
identityProviderModel.setAlias(IDENTITY_PROVIDER_ALIAS);
realm.addIdentityProvider(identityProviderModel);
s.identityProviders().create(identityProviderModel);
userId = s.users().addUser(realm, USERNAME).getId();
}