Do not return identity providers when querying the realm representation

Closes #21072

Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com>
This commit is contained in:
Pedro Igor 2024-08-06 10:04:10 -03:00
parent 4d64092119
commit 3ab2446074
8 changed files with 44 additions and 19 deletions

View file

@ -95,3 +95,11 @@ In the past, regaining access to a {project_name} instance when all admin users
It is now possible to run the `start` or `start-dev` commands with specific options to create a temporary admin account. Additionally, a new dedicated command has been introduced, which allows users to regain admin access without hassle. It is now possible to run the `start` or `start-dev` commands with specific options to create a temporary admin account. Additionally, a new dedicated command has been introduced, which allows users to regain admin access without hassle.
For detailed instructions and more information on this topic, refer to the link:{bootstrapadminrecovery_link}[{bootstrapadminrecovery_name}] guide. For detailed instructions and more information on this topic, refer to the link:{bootstrapadminrecovery_link}[{bootstrapadminrecovery_name}] guide.
= Identity Providers no longer available from the realm representation
As part of the improvements around the scalability of realms and organizations when they have many identity providers, the realm representation
no longer holds the list of identity providers. However, they are still available from the realm representation
when exporting a realm.
For information on how to migrate, see the link:{upgradingguide_link}[{upgradingguide_name}].

View file

@ -124,3 +124,12 @@ an existing Route53 configurations to avoid prolonged failover times due to clie
It used to be difficult to regain access to a {project_name} instance when all admin users were locked out. The process required multiple advanced steps, including direct database access and manual changes. In an effort to improve the user experience, {project_name} now provides multiple ways to bootstrap a new admin account, which can be used to recover from such situations. It used to be difficult to regain access to a {project_name} instance when all admin users were locked out. The process required multiple advanced steps, including direct database access and manual changes. In an effort to improve the user experience, {project_name} now provides multiple ways to bootstrap a new admin account, which can be used to recover from such situations.
Consequently, the environment variables `KEYCLOAK_ADMIN` and `KEYCLOAK_ADMIN_PASSWORD` have been deprecated. You should use `KC_BOOTSTRAP_ADMIN_USERNAME` and `KC_BOOTSTRAP_ADMIN_PASSWORD` instead. These are also general options, so they may be specified via the cli or other config sources, for example `--bootstrap-admin-username=admin`. For more information, see the new https://www.keycloak.org/server/bootstrap-admin-recovery[Bootstrap admin and recovery] guide. Consequently, the environment variables `KEYCLOAK_ADMIN` and `KEYCLOAK_ADMIN_PASSWORD` have been deprecated. You should use `KC_BOOTSTRAP_ADMIN_USERNAME` and `KC_BOOTSTRAP_ADMIN_PASSWORD` instead. These are also general options, so they may be specified via the cli or other config sources, for example `--bootstrap-admin-username=admin`. For more information, see the new https://www.keycloak.org/server/bootstrap-admin-recovery[Bootstrap admin and recovery] guide.
= Identity Providers no longer available from the realm representation
As part of the improvements around the scalability of realms and organizations when they have many identity providers, the realm representation
no longer holds the list of identity providers. However, they are still available from the realm representation
when exporting a realm.
To obtain the query the identity providers in a realm, prefer using the `/realms/{realm}/identity-provider/instances` endpoint.
This endpoint supports filters and pagination.

View file

@ -39,7 +39,7 @@ export const UserIdentityProviderLinks = ({
const [federatedId, setFederatedId] = useState(""); const [federatedId, setFederatedId] = useState("");
const [isLinkIdPModalOpen, setIsLinkIdPModalOpen] = useState(false); const [isLinkIdPModalOpen, setIsLinkIdPModalOpen] = useState(false);
const { realm, realmRepresentation } = useRealm(); const { realm } = useRealm();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();
const { t } = useTranslation(); const { t } = useTranslation();
const { hasAccess, hasSomeAccess } = useAccess(); const { hasAccess, hasSomeAccess } = useAccess();
@ -74,8 +74,8 @@ export const UserIdentityProviderLinks = ({
return allFedIds; return allFedIds;
}; };
const getAvailableIdPs = () => { const getAvailableIdPs = async () => {
return realmRepresentation?.identityProviders; return adminClient.identityProviders.find();
}; };
const linkedIdPsLoader = async () => { const linkedIdPsLoader = async () => {
@ -87,7 +87,7 @@ export const UserIdentityProviderLinks = ({
(x) => x.identityProvider, (x) => x.identityProvider,
); );
return getAvailableIdPs()?.filter( return (await getAvailableIdPs())?.filter(
(item) => !linkedNames.includes(item.alias), (item) => !linkedNames.includes(item.alias),
)!; )!;
}; };

View file

@ -503,13 +503,14 @@ public class ModelToRepresentation {
rep.setRequiredCredentials(reqCredentials); rep.setRequiredCredentials(reqCredentials);
} }
if (export) {
List<IdentityProviderRepresentation> identityProviders = realm.getIdentityProvidersStream() List<IdentityProviderRepresentation> identityProviders = realm.getIdentityProvidersStream()
.map(provider -> toRepresentation(realm, provider, export)).collect(Collectors.toList()); .map(provider -> toRepresentation(realm, provider, export)).collect(Collectors.toList());
rep.setIdentityProviders(identityProviders); rep.setIdentityProviders(identityProviders);
List<IdentityProviderMapperRepresentation> identityProviderMappers = realm.getIdentityProviderMappersStream() List<IdentityProviderMapperRepresentation> identityProviderMappers = realm.getIdentityProviderMappersStream()
.map(ModelToRepresentation::toRepresentation).collect(Collectors.toList()); .map(ModelToRepresentation::toRepresentation).collect(Collectors.toList());
rep.setIdentityProviderMappers(identityProviderMappers); rep.setIdentityProviderMappers(identityProviderMappers);
}
rep.setInternationalizationEnabled(realm.isInternationalizationEnabled()); rep.setInternationalizationEnabled(realm.isInternationalizationEnabled());
rep.setSupportedLocales(realm.getSupportedLocalesStream().collect(Collectors.toSet())); rep.setSupportedLocales(realm.getSupportedLocalesStream().collect(Collectors.toSet()));

View file

@ -58,6 +58,7 @@ import jakarta.ws.rs.core.Response;
import java.io.IOException; import java.io.IOException;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -186,7 +187,7 @@ public class IdentityProvidersResource {
maxResults = 100; // always set a maximum of 100 by default maxResults = 100; // always set a maximum of 100 by default
} }
Function<IdentityProviderModel, IdentityProviderRepresentation> toRepresentation = briefRepresentation != null && briefRepresentation Function<IdentityProviderModel, IdentityProviderRepresentation> toRepresentation = Optional.<Boolean>ofNullable(briefRepresentation).orElse(false)
? m -> ModelToRepresentation.toBriefRepresentation(realm, m) ? m -> ModelToRepresentation.toBriefRepresentation(realm, m)
: m -> StripSecretsUtils.stripSecrets(session, ModelToRepresentation.toRepresentation(realm, m)); : m -> StripSecretsUtils.stripSecrets(session, ModelToRepresentation.toRepresentation(realm, m));

View file

@ -389,12 +389,6 @@ public class RealmAdminResource {
rep.setRegistrationEmailAsUsername(realm.isRegistrationEmailAsUsername()); rep.setRegistrationEmailAsUsername(realm.isRegistrationEmailAsUsername());
} }
if (auth.realm().canViewIdentityProviders()) {
RealmRepresentation r = ModelToRepresentation.toRepresentation(session, realm, false);
rep.setIdentityProviders(r.getIdentityProviders());
rep.setIdentityProviderMappers(r.getIdentityProviderMappers());
}
return rep; return rep;
} }
} }

View file

@ -84,6 +84,7 @@ import org.keycloak.representations.idm.ErrorRepresentation;
import org.keycloak.representations.idm.IdentityProviderMapperRepresentation; import org.keycloak.representations.idm.IdentityProviderMapperRepresentation;
import org.keycloak.representations.idm.IdentityProviderMapperTypeRepresentation; import org.keycloak.representations.idm.IdentityProviderMapperTypeRepresentation;
import org.keycloak.representations.idm.IdentityProviderRepresentation; import org.keycloak.representations.idm.IdentityProviderRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.rotation.HardcodedKeyLocator; import org.keycloak.rotation.HardcodedKeyLocator;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants; import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ConfigurationException; import org.keycloak.saml.common.exceptions.ConfigurationException;
@ -566,6 +567,17 @@ public class IdentityProviderTest extends AbstractAdminTest {
} }
} }
@Test
public void testNotAvailableFromRealRepresentation() {
IdentityProviderRepresentation newIdentityProvider = createRep("remove-identity-provider", "saml");
create(newIdentityProvider);
RealmRepresentation rep = this.realm.toRepresentation();
assertNull(rep.getIdentityProviders());
assertNull(rep.getIdentityProviderMappers());
}
private void create(IdentityProviderRepresentation idpRep) { private void create(IdentityProviderRepresentation idpRep) {
Response response = realm.identityProviders().create(idpRep); Response response = realm.identityProviders().create(idpRep);
Assert.assertNotNull(ApiUtil.getCreatedId(response)); Assert.assertNotNull(ApiUtil.getCreatedId(response));

View file

@ -288,7 +288,7 @@ public class ExportImportUtil {
Assert.assertEquals("3025", smtpConfig.get("port")); Assert.assertEquals("3025", smtpConfig.get("port"));
// Test identity providers // Test identity providers
List<IdentityProviderRepresentation> identityProviders = realm.getIdentityProviders(); List<IdentityProviderRepresentation> identityProviders = realmRsc.identityProviders().findAll();
Assert.assertEquals(4, identityProviders.size()); Assert.assertEquals(4, identityProviders.size());
IdentityProviderRepresentation google = null; IdentityProviderRepresentation google = null;
for (IdentityProviderRepresentation idpRep : identityProviders) { for (IdentityProviderRepresentation idpRep : identityProviders) {