diff --git a/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties b/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties index a5b05a3b6a..8a286865bf 100644 --- a/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties +++ b/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties @@ -3244,6 +3244,8 @@ temporaryAdmin=Temporary admin user account. Ensure it is replaced with a perman temporaryService=Temporary admin service account. Ensure it is replaced with a permanent admin service account as soon as possible. addOrganizationAttributes.label=Add organization attributes addOrganizationAttributes.help=If enabled, the organization attributes will be available for each organization mapped to the token. +identityProviderUnlink=Unlink identity provider? +identityProviderUnlinkConfirm=Are you sure you want to unlink this identity provider? disableConfirmUserTitle=Disable user? disableConfirmUser=Are you sure you want to disable this user? eventTypes.UPDATE_CREDENTIAL.name=Update credential diff --git a/js/apps/admin-ui/src/organizations/IdentityProviderSelect.tsx b/js/apps/admin-ui/src/organizations/IdentityProviderSelect.tsx index 9912e4c47e..43b41f4c39 100644 --- a/js/apps/admin-ui/src/organizations/IdentityProviderSelect.tsx +++ b/js/apps/admin-ui/src/organizations/IdentityProviderSelect.tsx @@ -48,6 +48,7 @@ export const IdentityProviderSelect = ({ const { control, getValues, + setValue, formState: { errors }, } = useFormContext(); const values: string[] | undefined = getValues(name!); @@ -72,8 +73,7 @@ export const IdentityProviderSelect = ({ params.search = search; } - const idps = await adminClient.identityProviders.find(params); - return idps; + return await adminClient.identityProviders.find(params); }, setIdps, [search], @@ -85,7 +85,7 @@ export const IdentityProviderSelect = ({ const options = identityProviders.map((option) => ( {option!.alias} @@ -200,7 +200,9 @@ export const IdentityProviderSelect = ({ isOpen={open} selected={field.value} onSelect={(_, v) => { - const option = v?.toString(); + const idp = v as IdentityProviderRepresentation; + setValue("hideOnLogin", idp.hideOnLogin); + const option = idp.alias!; if (variant !== "typeaheadMulti") { const removed = field.value.includes(option); diff --git a/js/apps/admin-ui/src/organizations/IdentityProviders.tsx b/js/apps/admin-ui/src/organizations/IdentityProviders.tsx index 1670444874..26473cd069 100644 --- a/js/apps/admin-ui/src/organizations/IdentityProviders.tsx +++ b/js/apps/admin-ui/src/organizations/IdentityProviders.tsx @@ -43,10 +43,7 @@ const ShownOnLoginPageCheck = ({ { alias: row.alias! }, { ...row, - config: { - ...row.config, - "kc.org.broker.public": `${value}`, - }, + hideOnLogin: value, }, ); addAlert(t("linkUpdatedSuccessful")); @@ -61,7 +58,7 @@ const ShownOnLoginPageCheck = ({ toggle(value)} /> ); @@ -204,8 +201,8 @@ export const IdentityProviders = () => { displayKey: "providerDetails", }, { - name: "config['kc.org.broker.public']", - displayKey: "shownOnLoginPage", + name: "hideOnLogin", + displayKey: "hideOnLoginPage", cellRenderer: (row) => ( ), diff --git a/js/apps/admin-ui/src/organizations/LinkIdentityProviderModal.tsx b/js/apps/admin-ui/src/organizations/LinkIdentityProviderModal.tsx index 537db91933..b97f9252ef 100644 --- a/js/apps/admin-ui/src/organizations/LinkIdentityProviderModal.tsx +++ b/js/apps/admin-ui/src/organizations/LinkIdentityProviderModal.tsx @@ -29,9 +29,9 @@ type LinkIdentityProviderModalProps = { type LinkRepresentation = { alias: string[] | string; + hideOnLogin: boolean; config: { "kc.org.domain": string; - "kc.org.broker.public": string; }; }; @@ -51,7 +51,11 @@ export const LinkIdentityProviderModal = ({ useEffect( () => convertToFormValues( - { ...identityProvider, alias: [identityProvider?.alias] }, + { + ...identityProvider, + alias: [identityProvider?.alias], + hideOnLogin: identityProvider?.hideOnLogin, + }, setValue, ), [], @@ -72,6 +76,7 @@ export const LinkIdentityProviderModal = ({ ...foundIdentityProvider.config, ...config, }; + foundIdentityProvider.hideOnLogin = data.hideOnLogin; await adminClient.identityProviders.update( { alias: data.alias[0] }, foundIdentityProvider, @@ -140,10 +145,9 @@ export const LinkIdentityProviderModal = ({ menuAppendTo="parent" /> getLoginPredicate() { return ((Predicate) Objects::nonNull) - .and(idp -> idp.getOrganizationId() == null || Boolean.parseBoolean(idp.getConfig().get(OrganizationModel.BROKER_PUBLIC))) .and(Stream.of(values()).map(LoginFilter::getFilter).reduce(Predicate::and).get()); } } diff --git a/server-spi/src/main/java/org/keycloak/models/OrganizationModel.java b/server-spi/src/main/java/org/keycloak/models/OrganizationModel.java index e70b4c271c..389830183c 100644 --- a/server-spi/src/main/java/org/keycloak/models/OrganizationModel.java +++ b/server-spi/src/main/java/org/keycloak/models/OrganizationModel.java @@ -27,7 +27,6 @@ public interface OrganizationModel { String ORGANIZATION_ATTRIBUTE = "kc.org"; String ORGANIZATION_NAME_ATTRIBUTE = "kc.org.name"; String ORGANIZATION_DOMAIN_ATTRIBUTE = "kc.org.domain"; - String BROKER_PUBLIC = "kc.org.broker.public"; String ALIAS = "alias"; enum IdentityProviderRedirectMode { diff --git a/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderConfig.java b/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderConfig.java index f667ce4600..6cf0686366 100755 --- a/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderConfig.java +++ b/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderConfig.java @@ -71,12 +71,6 @@ public class SAMLIdentityProviderConfig extends IdentityProviderModel { public SAMLIdentityProviderConfig() { } - @Override - public void setHideOnLogin(boolean hideOnLogin) { - super.setHideOnLogin(hideOnLogin); - getConfig().put(LEGACY_HIDE_ON_LOGIN_ATTR, String.valueOf(hideOnLogin)); - } - public SAMLIdentityProviderConfig(IdentityProviderModel identityProviderModel) { super(identityProviderModel); } diff --git a/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderFactory.java b/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderFactory.java index 66d7b500cb..51c01cc233 100755 --- a/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderFactory.java +++ b/services/src/main/java/org/keycloak/broker/saml/SAMLIdentityProviderFactory.java @@ -40,6 +40,8 @@ import org.keycloak.saml.processing.core.saml.v2.util.SAMLMetadataUtil; import org.keycloak.saml.validators.DestinationValidator; import org.w3c.dom.Element; +import static org.keycloak.models.IdentityProviderModel.LEGACY_HIDE_ON_LOGIN_ATTR; + /** * @author Pedro Igor */ @@ -160,7 +162,7 @@ public class SAMLIdentityProviderFactory extends AbstractIdentityProviderFactory for (AttributeType attribute : entityType.getExtensions().getEntityAttributes().getAttribute()) { if (MACEDIR_ENTITY_CATEGORY.equals(attribute.getName()) && attribute.getAttributeValue().contains(REFEDS_HIDE_FROM_DISCOVERY)) { - samlIdentityProviderConfig.setHideOnLogin(true); + samlIdentityProviderConfig.getConfig().put(LEGACY_HIDE_ON_LOGIN_ATTR, String.valueOf(true)); } } diff --git a/services/src/main/java/org/keycloak/organization/authentication/authenticators/browser/OrganizationAuthenticator.java b/services/src/main/java/org/keycloak/organization/authentication/authenticators/browser/OrganizationAuthenticator.java index ea2187eb3f..37cf701e7f 100644 --- a/services/src/main/java/org/keycloak/organization/authentication/authenticators/browser/OrganizationAuthenticator.java +++ b/services/src/main/java/org/keycloak/organization/authentication/authenticators/browser/OrganizationAuthenticator.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.function.Function; +import java.util.function.Predicate; import java.util.stream.Stream; import jakarta.ws.rs.core.MultivaluedMap; @@ -287,7 +288,7 @@ public class OrganizationAuthenticator extends IdentityProviderAuthenticator { } private boolean hasPublicBrokers(OrganizationModel organization) { - return organization.getIdentityProviders().anyMatch(p -> Boolean.parseBoolean(p.getConfig().getOrDefault(OrganizationModel.BROKER_PUBLIC, Boolean.FALSE.toString()))); + return organization.getIdentityProviders().anyMatch(Predicate.not(IdentityProviderModel::isHideOnLogin)); } private OrganizationProvider getOrganizationProvider() { diff --git a/services/src/main/java/org/keycloak/organization/forms/login/freemarker/model/OrganizationAwareIdentityProviderBean.java b/services/src/main/java/org/keycloak/organization/forms/login/freemarker/model/OrganizationAwareIdentityProviderBean.java index bf67dff185..3117c75f1f 100644 --- a/services/src/main/java/org/keycloak/organization/forms/login/freemarker/model/OrganizationAwareIdentityProviderBean.java +++ b/services/src/main/java/org/keycloak/organization/forms/login/freemarker/model/OrganizationAwareIdentityProviderBean.java @@ -64,8 +64,7 @@ public class OrganizationAwareIdentityProviderBean extends IdentityProviderBean // we already have the organization, just fetch the organization's public enabled IDPs. if (this.organization != null) { return organization.getIdentityProviders() - .filter(idp -> idp.isEnabled() && !idp.isLinkOnly() && !idp.isHideOnLogin() - && Boolean.parseBoolean(idp.getConfig().get(OrganizationModel.BROKER_PUBLIC))) + .filter(idp -> idp.isEnabled() && !idp.isLinkOnly() && !idp.isHideOnLogin()) .filter(idp -> !Objects.equals(existingIDP, idp.getAlias())) .map(idp -> createIdentityProvider(super.realm, super.baseURI, idp)) .sorted(IDP_COMPARATOR_INSTANCE).toList(); @@ -104,6 +103,6 @@ public class OrganizationAwareIdentityProviderBean extends IdentityProviderBean if (organization != null && !Objects.equals(organization.getId(),idp.getOrganizationId())) { return false; } - return Boolean.parseBoolean(idp.getConfig().getOrDefault(OrganizationModel.BROKER_PUBLIC, Boolean.FALSE.toString())); + return !idp.isHideOnLogin(); } } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java index 5c32de3693..77b0b56dc8 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java @@ -1088,8 +1088,7 @@ public class IdentityProviderTest extends AbstractAdminTest { // import endpoint simply converts IDPSSODescriptor into key value pairs. // check that saml-idp-metadata.xml was properly converted into key value pairs //System.out.println(config); - assertThat(config.keySet(), containsInAnyOrder( - "syncMode", + List keys = new ArrayList<>(List.of("syncMode", "validateSignature", "singleLogoutServiceUrl", "postBindingLogout", @@ -1103,9 +1102,12 @@ public class IdentityProviderTest extends AbstractAdminTest { "signingCertificate", "addExtensionsElementWithKeyInfo", "loginHint", - "hideOnLoginPage", "idpEntityId" )); + if (hasHideOnLoginPage) { + keys.add("hideOnLoginPage"); + } + assertThat(config.keySet(), containsInAnyOrder(keys.toArray())); assertThat(config, hasEntry("validateSignature", "true")); assertThat(config, hasEntry("singleLogoutServiceUrl", "http://localhost:8080/auth/realms/master/protocol/saml")); assertThat(config, hasEntry("artifactResolutionServiceUrl", "http://localhost:8080/auth/realms/master/protocol/saml/resolve")); @@ -1116,7 +1118,9 @@ public class IdentityProviderTest extends AbstractAdminTest { assertThat(config, hasEntry("wantAuthnRequestsSigned", "true")); assertThat(config, hasEntry("addExtensionsElementWithKeyInfo", "false")); assertThat(config, hasEntry("nameIDPolicyFormat", "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent")); - assertThat(config, hasEntry("hideOnLoginPage", "true")); + if (hasHideOnLoginPage) { + assertThat(config, hasEntry("hideOnLoginPage", "true")); + } assertThat(config, hasEntry("idpEntityId", "http://localhost:8080/auth/realms/master")); assertThat(config, hasEntry(is("signingCertificate"), notNullValue())); } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/admin/AbstractOrganizationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/admin/AbstractOrganizationTest.java index d71d50f5ff..90bf1728c1 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/admin/AbstractOrganizationTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/admin/AbstractOrganizationTest.java @@ -121,9 +121,9 @@ public abstract class AbstractOrganizationTest extends AbstractAdminTest { return createOrganization(realm, getCleanup(), name, brokerConfigFunction.apply(name).setUpIdentityProvider(), orgDomains); } - protected OrganizationRepresentation createOrganization(String name, Map brokerConfig) { + protected OrganizationRepresentation createOrganization(String name, boolean isBrokerPublic) { IdentityProviderRepresentation broker = brokerConfigFunction.apply(name).setUpIdentityProvider(); - broker.getConfig().putAll(brokerConfig); + broker.setHideOnLogin(!isBrokerPublic); return createOrganization(testRealm(), getCleanup(), name, broker, name + ".org"); } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/broker/AbstractBrokerSelfRegistrationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/broker/AbstractBrokerSelfRegistrationTest.java index 7473f9b61d..3af20687e8 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/broker/AbstractBrokerSelfRegistrationTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/broker/AbstractBrokerSelfRegistrationTest.java @@ -107,7 +107,7 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz public void testIdentityFirstUserNotExistEmailMatchBrokerDomainAndBrokerIsPublic() { OrganizationResource organization = testRealm().organizations().get(createOrganization().getId()); IdentityProviderRepresentation idpRep = organization.identityProviders().getIdentityProviders().get(0); - idpRep.getConfig().put(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString()); + idpRep.setHideOnLogin(false); idpRep.getConfig().remove(OrganizationModel.ORGANIZATION_DOMAIN_ATTRIBUTE); testRealm().identityProviders().get(idpRep.getAlias()).update(idpRep); @@ -153,8 +153,8 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz idp = bc.setUpIdentityProvider(); idp.setAlias("second-idp"); idp.setInternalId(null); + idp.setHideOnLogin(false); idp.getConfig().remove(OrganizationModel.ORGANIZATION_DOMAIN_ATTRIBUTE); - idp.getConfig().put(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString()); // create a second broker without a domain set testRealm().identityProviders().create(idp).close(); getCleanup().addCleanup(testRealm().identityProviders().get("second-idp")::remove); @@ -167,7 +167,7 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz Assert.assertFalse(loginPage.isSocialButtonPresent(bc.getIDPAlias())); Assert.assertTrue(loginPage.isSocialButtonPresent(idp.getAlias())); - idp.getConfig().put(OrganizationModel.BROKER_PUBLIC, Boolean.FALSE.toString()); + idp.setHideOnLogin(true); testRealm().identityProviders().get(idp.getAlias()).update(idp); driver.navigate().refresh(); Assert.assertTrue(loginPage.isPasswordInputPresent()); @@ -207,6 +207,7 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz IdentityProviderRepresentation idp = bc.setUpIdentityProvider(); idp.setAlias("realm-level-idp"); + idp.setHideOnLogin(false); Assert.assertFalse(loginPage.isSocialButtonPresent(idp.getAlias())); testRealm().identityProviders().create(idp).close(); @@ -224,7 +225,7 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz OrganizationResource organization = testRealm().organizations().get(createOrganization().getId()); OrganizationIdentityProviderResource broker = organization.identityProviders().get(bc.getIDPAlias()); IdentityProviderRepresentation brokerRep = broker.toRepresentation(); - brokerRep.getConfig().put(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString()); + brokerRep.setHideOnLogin(false); brokerRep.getConfig().remove(IdentityProviderRedirectMode.EMAIL_MATCH.getKey()); testRealm().identityProviders().get(brokerRep.getAlias()).update(brokerRep); @@ -248,8 +249,8 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz OrganizationResource organization = testRealm().organizations().get(createOrganization().getId()); OrganizationIdentityProviderResource broker = organization.identityProviders().get(bc.getIDPAlias()); IdentityProviderRepresentation brokerRep = broker.toRepresentation(); + brokerRep.setHideOnLogin(false); brokerRep.getConfig().remove(IdentityProviderRedirectMode.EMAIL_MATCH.getKey()); - brokerRep.getConfig().put(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString()); testRealm().identityProviders().get(brokerRep.getAlias()).update(brokerRep); openIdentityFirstLoginPage(bc.getUserEmail(), true, brokerRep.getAlias(), false, true); @@ -302,13 +303,14 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz OrganizationResource organization = testRealm().organizations().get(createOrganization().getId()); OrganizationIdentityProviderResource broker = organization.identityProviders().get(bc.getIDPAlias()); IdentityProviderRepresentation brokerRep = broker.toRepresentation(); + brokerRep.setHideOnLogin(false); brokerRep.getConfig().put(IdentityProviderRedirectMode.EMAIL_MATCH.getKey(), Boolean.FALSE.toString()); testRealm().identityProviders().get(brokerRep.getAlias()).update(brokerRep); IdentityProviderRepresentation secondIdp = bc.setUpIdentityProvider(); secondIdp.setAlias("second-idp"); secondIdp.setInternalId(null); + secondIdp.setHideOnLogin(false); secondIdp.getConfig().remove(OrganizationModel.ORGANIZATION_DOMAIN_ATTRIBUTE); - secondIdp.getConfig().put(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString()); testRealm().identityProviders().create(secondIdp).close(); getCleanup().addCleanup(testRealm().identityProviders().get("second-idp")::remove); organization.identityProviders().addIdentityProvider(secondIdp.getAlias()).close(); @@ -350,7 +352,7 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz public void testNoIDPRedirectWhenUserHasCredentialsSet() { OrganizationResource organization = testRealm().organizations().get(createOrganization().getId()); IdentityProviderRepresentation idpRep = organization.identityProviders().getIdentityProviders().get(0); - idpRep.getConfig().put(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString()); + idpRep.setHideOnLogin(false); testRealm().identityProviders().get(idpRep.getAlias()).update(idpRep); assertBrokerRegistration(organization, bc.getUserLogin(), bc.getUserEmail()); @@ -467,9 +469,9 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz public void testDoNotRedirectToIdentityProviderAssociatedWithOrganizationDomain() { OrganizationResource organization = testRealm().organizations().get(createOrganization().getId()); IdentityProviderRepresentation idp = organization.identityProviders().get(bc.getIDPAlias()).toRepresentation(); + idp.setHideOnLogin(false); idp.getConfig().put(OrganizationModel.ORGANIZATION_DOMAIN_ATTRIBUTE, "neworg.org"); idp.getConfig().put(IdentityProviderRedirectMode.EMAIL_MATCH.getKey(), Boolean.FALSE.toString()); - idp.getConfig().put(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString()); testRealm().identityProviders().get(bc.getIDPAlias()).update(idp); openIdentityFirstLoginPage(bc.getUserEmail(), false, idp.getAlias(), false, false); @@ -484,15 +486,15 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz String org0Name = "org-0"; OrganizationResource org0 = testRealm().organizations().get(createOrganization(org0Name).getId()); IdentityProviderRepresentation org0Broker = org0.identityProviders().getIdentityProviders().get(0); + org0Broker.setHideOnLogin(false); org0Broker.getConfig().remove(OrganizationModel.ORGANIZATION_DOMAIN_ATTRIBUTE); - org0Broker.getConfig().put(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString()); testRealm().identityProviders().get(org0Broker.getAlias()).update(org0Broker); String org1Name = "org-1"; OrganizationResource org1 = testRealm().organizations().get(createOrganization(org1Name).getId()); IdentityProviderRepresentation org1Broker = org1.identityProviders().getIdentityProviders().get(0); + org1Broker.setHideOnLogin(false); org1Broker.getConfig().remove(OrganizationModel.ORGANIZATION_DOMAIN_ATTRIBUTE); org1Broker.getConfig().remove(IdentityProviderRedirectMode.EMAIL_MATCH.getKey()); - org1Broker.getConfig().put(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString()); testRealm().identityProviders().get(org1Broker.getAlias()).update(org1Broker); oauth.clientId("broker-app"); @@ -520,8 +522,8 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz idp = bc.setUpIdentityProvider(); idp.setAlias("second-idp"); idp.setInternalId(null); + idp.setHideOnLogin(false); idp.getConfig().remove(OrganizationModel.ORGANIZATION_DOMAIN_ATTRIBUTE); - idp.getConfig().put(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString()); // create a second broker without a domain set testRealm().identityProviders().create(idp).close(); getCleanup().addCleanup(testRealm().identityProviders().get("second-idp")::remove); @@ -556,8 +558,8 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz idp = bc.setUpIdentityProvider(); idp.setAlias("second-idp"); idp.setInternalId(null); + idp.setHideOnLogin(false); idp.getConfig().put(OrganizationModel.ORGANIZATION_DOMAIN_ATTRIBUTE, "other.org"); - idp.getConfig().put(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString()); // create a second broker without a domain set testRealm().identityProviders().create(idp).close(); getCleanup().addCleanup(testRealm().identityProviders().get("second-idp")::remove); @@ -590,7 +592,7 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz idp = bc.setUpIdentityProvider(); idp.setAlias("second-idp"); idp.setInternalId(null); - idp.getConfig().put(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString()); + idp.setHideOnLogin(false); // create a second broker without a domain set testRealm().identityProviders().create(idp).close(); getCleanup().addCleanup(testRealm().identityProviders().get("second-idp")::remove); @@ -609,6 +611,7 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz IdentityProviderRepresentation idp = bc.setUpIdentityProvider(); idp.setAlias("realm-idp"); idp.setInternalId(null); + idp.setHideOnLogin(false); // create a second broker without a domain set testRealm().identityProviders().create(idp).close(); @@ -628,7 +631,7 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz IdentityProviderRepresentation idpRep = organization.identityProviders().getIdentityProviders().get(0); // make sure the user can select this idp from the organization when authenticating - idpRep.getConfig().put(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString()); + idpRep.setHideOnLogin(false); idpRep.getConfig().remove(OrganizationModel.ORGANIZATION_DOMAIN_ATTRIBUTE); testRealm().identityProviders().get(idpRep.getAlias()).update(idpRep); @@ -653,7 +656,7 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz IdentityProviderRepresentation idpRep = organization.identityProviders().getIdentityProviders().get(0); // make sure the user can select this idp from the organization when authenticating - idpRep.getConfig().put(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString()); + idpRep.setHideOnLogin(false); idpRep.getConfig().remove(OrganizationModel.ORGANIZATION_DOMAIN_ATTRIBUTE); testRealm().identityProviders().get(idpRep.getAlias()).update(idpRep); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/broker/BrokerConfigurationWrapper.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/broker/BrokerConfigurationWrapper.java index 7bdad6915c..d1c6ad0e63 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/broker/BrokerConfigurationWrapper.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/broker/BrokerConfigurationWrapper.java @@ -81,6 +81,8 @@ public class BrokerConfigurationWrapper implements BrokerConfiguration { public IdentityProviderRepresentation setUpIdentityProvider() { IdentityProviderRepresentation broker = delegate.setUpIdentityProvider(); broker.setAlias(getIDPAlias()); + // by default set the test org idps as not available for login pages. + broker.setHideOnLogin(true); return broker; } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/broker/OrganizationIdentityProviderTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/broker/OrganizationIdentityProviderTest.java index ca7cb50312..47b2d5b460 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/broker/OrganizationIdentityProviderTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/broker/OrganizationIdentityProviderTest.java @@ -23,7 +23,6 @@ import static org.junit.Assert.assertFalse; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertNotNull; -import static org.keycloak.models.OrganizationModel.BROKER_PUBLIC; import static org.keycloak.models.OrganizationModel.ORGANIZATION_DOMAIN_ATTRIBUTE; import jakarta.ws.rs.BadRequestException; @@ -111,7 +110,6 @@ public class OrganizationIdentityProviderTest extends AbstractOrganizationTest { //remove Org related stuff from the template idpTemplate.setOrganizationId(null); idpTemplate.getConfig().remove(OrganizationModel.ORGANIZATION_DOMAIN_ATTRIBUTE); - idpTemplate.getConfig().remove(OrganizationModel.BROKER_PUBLIC); idpTemplate.getConfig().remove(OrganizationModel.IdentityProviderRedirectMode.EMAIL_MATCH.getKey()); for (int i = 0; i < 5; i++) { @@ -191,7 +189,6 @@ public class OrganizationIdentityProviderTest extends AbstractOrganizationTest { // broker no longer linked to the org Assert.assertNull(idpRep.getOrganizationId()); Assert.assertNull(idpRep.getConfig().get(ORGANIZATION_DOMAIN_ATTRIBUTE)); - Assert.assertNull(idpRep.getConfig().get(BROKER_PUBLIC)); } @Test diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/cache/OrganizationCacheTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/cache/OrganizationCacheTest.java index d14058f8b2..c799b88a91 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/cache/OrganizationCacheTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/cache/OrganizationCacheTest.java @@ -290,8 +290,8 @@ public class OrganizationCacheTest extends AbstractOrganizationTest { IdentityProviderRepresentation idpRep = testRealm().identityProviders().get("orga-identity-provider").toRepresentation(); idpRep.setInternalId(null); idpRep.setOrganizationId(null); + idpRep.setHideOnLogin(false); idpRep.getConfig().remove(OrganizationModel.ORGANIZATION_DOMAIN_ATTRIBUTE); - idpRep.getConfig().put(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString()); for (int i = 0; i < 10; i++) { final String alias = "org-idp-" + i; @@ -372,8 +372,6 @@ public class OrganizationCacheTest extends AbstractOrganizationTest { idpRep.setEnabled((i % 2) == 0); // half of the IDPs will be disabled and won't qualify for login. idpRep.setDisplayName("Broker " + i); idpRep.setProviderId("keycloak-oidc"); - if (i >= 10) - idpRep.getConfig().put(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString()); testRealm().identityProviders().create(idpRep).close(); getCleanup().addCleanup(testRealm().identityProviders().get("alias")::remove); } @@ -497,7 +495,6 @@ public class OrganizationCacheTest extends AbstractOrganizationTest { // 4- finally, change one of the realm-level login IDPs, linking it to an org - although it still qualifies for login, it is now // linked to an org, which should invalidate all login caches. idpRep = testRealm().identityProviders().get("idp-alias-20").toRepresentation(); - idpRep.getConfig().put(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString()); testRealm().identityProviders().get("idp-alias-20").update(idpRep); testRealm().organizations().get(orgaId).identityProviders().addIdentityProvider("idp-alias-20"); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/mapper/OrganizationOIDCProtocolMapperTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/mapper/OrganizationOIDCProtocolMapperTest.java index 65bbffce85..31f79df841 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/mapper/OrganizationOIDCProtocolMapperTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/mapper/OrganizationOIDCProtocolMapperTest.java @@ -46,7 +46,6 @@ import org.keycloak.admin.client.resource.ClientScopeResource; import org.keycloak.admin.client.resource.OrganizationResource; import org.keycloak.common.util.MultivaluedHashMap; import org.keycloak.common.util.UriUtils; -import org.keycloak.models.OrganizationModel; import org.keycloak.organization.protocol.mappers.oidc.OrganizationMembershipMapper; import org.keycloak.protocol.ProtocolMapperUtils; import org.keycloak.protocol.oidc.OIDCLoginProtocol; @@ -125,9 +124,9 @@ public class OrganizationOIDCProtocolMapperTest extends AbstractOrganizationTest @SuppressWarnings("unchecked") @Test public void testOrganizationScopeMapsSpecificOrganization() { - OrganizationRepresentation orgA = createOrganization("orga", Map.of(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString())); + OrganizationRepresentation orgA = createOrganization("orga", true); MemberRepresentation member = addMember(testRealm().organizations().get(orgA.getId()), "member@" + orgA.getDomains().iterator().next().getName()); - OrganizationRepresentation orgB = createOrganization("orgb", Map.of(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString())); + OrganizationRepresentation orgB = createOrganization("orgb", true); testRealm().organizations().get(orgB.getId()).members().addMember(member.getId()).close(); // resolve organization based on the organization scope value @@ -156,9 +155,9 @@ public class OrganizationOIDCProtocolMapperTest extends AbstractOrganizationTest @Test public void testOrganizationScopeMapsAllOrganizations() { - OrganizationRepresentation orgA = createOrganization("orga", Map.of(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString())); + OrganizationRepresentation orgA = createOrganization("orga", true); MemberRepresentation member = addMember(testRealm().organizations().get(orgA.getId()), "member@" + orgA.getDomains().iterator().next().getName()); - OrganizationRepresentation orgB = createOrganization("orgb", Map.of(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString())); + OrganizationRepresentation orgB = createOrganization("orgb", true); testRealm().organizations().get(orgB.getId()).members().addMember(member.getId()).close(); // resolve organization based on the organization scope value @@ -204,7 +203,7 @@ public class OrganizationOIDCProtocolMapperTest extends AbstractOrganizationTest @Test public void testOrganizationScopeAnyMapsSingleOrganization() { - OrganizationRepresentation orgA = createOrganization("orga", Map.of(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString())); + OrganizationRepresentation orgA = createOrganization("orga", true); MemberRepresentation member = addMember(testRealm().organizations().get(orgA.getId()), "member@" + orgA.getDomains().iterator().next().getName()); // resolve organization based on the organization scope value @@ -220,9 +219,9 @@ public class OrganizationOIDCProtocolMapperTest extends AbstractOrganizationTest @Test public void testOrganizationScopeAnyAskUserToSelectOrganization() { - OrganizationRepresentation orgA = createOrganization("orga", Map.of(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString())); + OrganizationRepresentation orgA = createOrganization("orga", true); MemberRepresentation member = addMember(testRealm().organizations().get(orgA.getId()), "member@" + orgA.getDomains().iterator().next().getName()); - OrganizationRepresentation orgB = createOrganization("orgb", Map.of(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString())); + OrganizationRepresentation orgB = createOrganization("orgb", true); testRealm().organizations().get(orgB.getId()).members().addMember(member.getId()).close(); oauth.clientId("broker-app"); oauth.scope("organization"); @@ -248,9 +247,9 @@ public class OrganizationOIDCProtocolMapperTest extends AbstractOrganizationTest @Test public void testRefreshTokenWithAllOrganizationsAskingForSpecificOrganization() { - OrganizationRepresentation orgA = createOrganization("orga", Map.of(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString())); + OrganizationRepresentation orgA = createOrganization("orga", true); MemberRepresentation member = addMember(testRealm().organizations().get(orgA.getId()), "member@" + orgA.getDomains().iterator().next().getName()); - OrganizationRepresentation orgB = createOrganization("orgb", Map.of(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString())); + OrganizationRepresentation orgB = createOrganization("orgb", true); testRealm().organizations().get(orgB.getId()).members().addMember(member.getId()).close(); // identity-first login will respect the organization provided in the scope even though the user email maps to a different organization oauth.clientId("broker-app"); @@ -281,9 +280,9 @@ public class OrganizationOIDCProtocolMapperTest extends AbstractOrganizationTest @Test public void testRefreshTokenWithSingleOrganizationsAskingAllOrganizations() { - OrganizationRepresentation orgA = createOrganization("orga", Map.of(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString())); + OrganizationRepresentation orgA = createOrganization("orga", true); MemberRepresentation member = addMember(testRealm().organizations().get(orgA.getId()), "member@" + orgA.getDomains().iterator().next().getName()); - OrganizationRepresentation orgB = createOrganization("orgb", Map.of(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString())); + OrganizationRepresentation orgB = createOrganization("orgb", true); testRealm().organizations().get(orgB.getId()).members().addMember(member.getId()).close(); // identity-first login will respect the organization provided in the scope even though the user email maps to a different organization oauth.clientId("broker-app"); @@ -316,9 +315,9 @@ public class OrganizationOIDCProtocolMapperTest extends AbstractOrganizationTest @Test public void testRefreshTokenWithSingleOrganizationsAskingDifferentOrganization() { - OrganizationRepresentation orgA = createOrganization("orga", Map.of(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString())); + OrganizationRepresentation orgA = createOrganization("orga", true); MemberRepresentation member = addMember(testRealm().organizations().get(orgA.getId()), "member@" + orgA.getDomains().iterator().next().getName()); - OrganizationRepresentation orgB = createOrganization("orgb", Map.of(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString())); + OrganizationRepresentation orgB = createOrganization("orgb", true); testRealm().organizations().get(orgB.getId()).members().addMember(member.getId()).close(); // identity-first login will respect the organization provided in the scope even though the user email maps to a different organization oauth.clientId("broker-app"); @@ -349,9 +348,9 @@ public class OrganizationOIDCProtocolMapperTest extends AbstractOrganizationTest @Test public void testRefreshTokenScopeAnyAskingAllOrganizations() { - OrganizationRepresentation orgA = createOrganization("orga", Map.of(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString())); + OrganizationRepresentation orgA = createOrganization("orga", true); MemberRepresentation member = addMember(testRealm().organizations().get(orgA.getId()), "member@" + orgA.getDomains().iterator().next().getName()); - OrganizationRepresentation orgB = createOrganization("orgb", Map.of(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString())); + OrganizationRepresentation orgB = createOrganization("orgb", true); testRealm().organizations().get(orgB.getId()).members().addMember(member.getId()).close(); oauth.clientId("broker-app"); String originalScope = "organization"; @@ -385,9 +384,9 @@ public class OrganizationOIDCProtocolMapperTest extends AbstractOrganizationTest @Test public void testRefreshTokenScopeAnyAskingSingleOrganization() { - OrganizationRepresentation orgA = createOrganization("orga", Map.of(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString())); + OrganizationRepresentation orgA = createOrganization("orga", true); MemberRepresentation member = addMember(testRealm().organizations().get(orgA.getId()), "member@" + orgA.getDomains().iterator().next().getName()); - OrganizationRepresentation orgB = createOrganization("orgb", Map.of(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString())); + OrganizationRepresentation orgB = createOrganization("orgb", true); testRealm().organizations().get(orgB.getId()).members().addMember(member.getId()).close(); oauth.clientId("broker-app"); String originalScope = "organization"; @@ -455,9 +454,9 @@ public class OrganizationOIDCProtocolMapperTest extends AbstractOrganizationTest @Test public void testOrganizationsClaimAsList() throws Exception { - OrganizationRepresentation orgA = createOrganization("orga", Map.of(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString())); + OrganizationRepresentation orgA = createOrganization("orga", true); MemberRepresentation member = addMember(testRealm().organizations().get(orgA.getId()), "member@" + orgA.getDomains().iterator().next().getName()); - OrganizationRepresentation orgB = createOrganization("orgb", Map.of(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString())); + OrganizationRepresentation orgB = createOrganization("orgb", true); testRealm().organizations().get(orgB.getId()).members().addMember(member.getId()).close(); setMapperConfig(OIDCAttributeMapperHelper.JSON_TYPE, "String"); @@ -473,9 +472,9 @@ public class OrganizationOIDCProtocolMapperTest extends AbstractOrganizationTest @Test public void testOrganizationsClaimSingleValued() throws Exception { - OrganizationRepresentation orgA = createOrganization("orga", Map.of(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString())); + OrganizationRepresentation orgA = createOrganization("orga", true); MemberRepresentation member = addMember(testRealm().organizations().get(orgA.getId()), "member@" + orgA.getDomains().iterator().next().getName()); - OrganizationRepresentation orgB = createOrganization("orgb", Map.of(OrganizationModel.BROKER_PUBLIC, Boolean.TRUE.toString())); + OrganizationRepresentation orgB = createOrganization("orgb", true); testRealm().organizations().get(orgB.getId()).members().addMember(member.getId()).close(); setMapperConfig(ProtocolMapperUtils.MULTIVALUED, Boolean.FALSE.toString()); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/member/OrganizationMemberTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/member/OrganizationMemberTest.java index 6862ac115c..5afd937be7 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/member/OrganizationMemberTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/organization/member/OrganizationMemberTest.java @@ -430,6 +430,7 @@ public class OrganizationMemberTest extends AbstractOrganizationTest { // create non-org idp in a realm String idpAlias = "former-non-org-identity-provider"; IdentityProviderRepresentation idpRep = brokerConfigFunction.apply("former-non-org").setUpIdentityProvider(); + idpRep.setHideOnLogin(false); try (Response response = testRealm().identityProviders().create(idpRep)) { assertThat(response.getStatus(), equalTo(Status.CREATED.getStatusCode())); getCleanup().addCleanup(testRealm().identityProviders().get(bc.getIDPAlias())::remove);