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:
parent
67b6cf7eac
commit
aeb1951aba
38 changed files with 310 additions and 195 deletions
|
@ -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);
|
||||
|
|
|
@ -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(this.getAliasSearchPredicate(search, builder, idp));
|
||||
}
|
||||
|
||||
predicates.add(builder.like(builder.lower(idp.get("alias")), search.toLowerCase(), '\\'));
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
session.identityProviders().getAllStream(Map.of(IdentityProviderModel.FIRST_BROKER_LOGIN_FLOW_ID, ""), null, null)
|
||||
.forEach(provider -> {
|
||||
provider.setFirstBrokerLoginFlowId(firstBrokerLoginFlow.getId());
|
||||
realm.updateIdentityProvider(provider);
|
||||
session.identityProviders().update(provider);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -52,11 +52,11 @@ public class LoginFormsUtil {
|
|||
// 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
|
||||
// - 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
|
||||
// - 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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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,12 +518,18 @@ 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);
|
||||
// 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 (idpModel.getAlias().equals(issuer) || external.isIssuer(issuer, formParams)) {
|
||||
if (external.isIssuer(issuer, formParams)) {
|
||||
externalIdp.set(external);
|
||||
externalIdpModel.set(idpModel);
|
||||
return true;
|
||||
|
@ -531,7 +537,7 @@ public class DefaultTokenExchangeProvider implements TokenExchangeProvider {
|
|||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue