mirror of
https://github.com/keycloak/keycloak.git
synced 2026-05-28 04:13:22 -04:00
Allow hide organization brokers when the user does not map to any organization during login
Closes #45422 Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com>
This commit is contained in:
parent
45e59d8181
commit
37ff64446b
6 changed files with 72 additions and 3 deletions
|
|
@ -42,6 +42,9 @@ The domain from the organization that you want to link with the identity provide
|
|||
Hide on login page::
|
||||
If this identity provider should be hidden in login pages when the user is authenticating in the scope of the organization.
|
||||
|
||||
Hide on login page when organization not resolved::
|
||||
If enabled, the identity provider will be hidden on the login page when the organization cannot be resolved based on the user's email domain. Otherwise, the identity provider will be shown on the login page regardless of whether the organization is resolved or not. If 'Hide on login page' is also enabled, the identity provider will always be hidden on the login page.
|
||||
|
||||
Redirect when email domain matches::
|
||||
If members should be automatically redirected to the identity provider when their email domain matches the domain set to the identity provider. If the domain is set to `Any`, members whose email domain matches *any* of the organization domains will be redirected to the identity provider.
|
||||
|
||||
|
|
|
|||
|
|
@ -3710,4 +3710,6 @@ smtpSocketWriteTimeoutHelp=The timeout in milliseconds for writing to the SMTP s
|
|||
eventTypes.USER_SESSION_DELETED.name=User session deleted
|
||||
eventTypes.USER_SESSION_DELETED.description=User session deleted
|
||||
eventTypes.USER_SESSION_DELETED_ERROR.name=User session deleted error
|
||||
eventTypes.USER_SESSION_DELETED_ERROR.description=User session deleted error
|
||||
eventTypes.USER_SESSION_DELETED_ERROR.description=User session deleted error
|
||||
hideOnLoginWhenOrgNotResolved=Hide on login page when organization not resolved
|
||||
hideOnLoginWhenOrgNotResolvedHelp=If enabled, the identity provider will be hidden on the login page when the organization cannot be resolved based on the user's email domain. Otherwise, the identity provider will be shown on the login page regardless of whether the organization is resolved or not. If 'Hide on login page' is also enabled, the identity provider will always be hidden on the login page.
|
||||
|
|
@ -153,6 +153,14 @@ export const LinkIdentityProviderModal = ({
|
|||
labelIcon={t("hideOnLoginPageHelp")}
|
||||
defaultValue={true}
|
||||
/>
|
||||
<DefaultSwitchControl
|
||||
name={convertAttributeNameToForm(
|
||||
"config.kc.org.broker.login.hide-when-org-unknown",
|
||||
)}
|
||||
label={t("hideOnLoginWhenOrgNotResolved")}
|
||||
labelIcon={t("hideOnLoginWhenOrgNotResolvedHelp")}
|
||||
stringify
|
||||
/>
|
||||
<DefaultSwitchControl
|
||||
name={convertAttributeNameToForm(
|
||||
"config.kc.org.broker.redirect.mode.email-matches",
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ public interface OrganizationModel {
|
|||
String ORGANIZATION_NAME_ATTRIBUTE = "kc.org.name";
|
||||
String ORGANIZATION_DOMAIN_ATTRIBUTE = "kc.org.domain";
|
||||
String ALIAS = "alias";
|
||||
String HIDE_IDP_ON_LOGIN_WHEN_ORGANIZATION_UNKNOWN = "kc.org.broker.login.hide-when-org-unknown";
|
||||
|
||||
enum IdentityProviderRedirectMode {
|
||||
EMAIL_MATCH("kc.org.broker.redirect.mode.email-matches");
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
package org.keycloak.organization.forms.login.freemarker.model;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
|
|
@ -61,6 +62,18 @@ public class OrganizationAwareIdentityProviderBean extends IdentityProviderBean
|
|||
.map(idp -> createIdentityProvider(this.realm, this.baseURI, idp))
|
||||
.sorted(IDP_COMPARATOR_INSTANCE).toList();
|
||||
}
|
||||
Predicate<IdentityProviderModel> defaultFilter = idp -> {
|
||||
if (idp.isEnabled() && !Objects.equals(existingIDP, idp.getAlias())) {
|
||||
if (organization == null) {
|
||||
Map<String, String> config = idp.getConfig();
|
||||
return !Boolean.parseBoolean(config.get(OrganizationModel.HIDE_IDP_ON_LOGIN_WHEN_ORGANIZATION_UNKNOWN));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
if (onlyOrganizationBrokers) {
|
||||
// we already have the organization, just fetch the organization's public enabled IDPs.
|
||||
if (this.organization != null) {
|
||||
|
|
@ -72,12 +85,12 @@ public class OrganizationAwareIdentityProviderBean extends IdentityProviderBean
|
|||
}
|
||||
// we don't have a specific organization - fetch public enabled IDPs linked to any org.
|
||||
return session.identityProviders().getForLogin(ORG_ONLY, null)
|
||||
.filter(idp -> idp.isEnabled() && !Objects.equals(existingIDP, idp.getAlias())) // re-check isEnabled as idp might have been wrapped.
|
||||
.filter(defaultFilter) // re-check isEnabled as idp might have been wrapped.
|
||||
.map(idp -> createIdentityProvider(this.realm, this.baseURI, idp))
|
||||
.sorted(IDP_COMPARATOR_INSTANCE).toList();
|
||||
}
|
||||
return session.identityProviders().getForLogin(ALL, this.organization != null ? this.organization.getId() : null)
|
||||
.filter(idp -> idp.isEnabled() && !Objects.equals(existingIDP, idp.getAlias())) // re-check isEnabled as idp might have been wrapped.
|
||||
.filter(defaultFilter) // re-check isEnabled as idp might have been wrapped.
|
||||
.map(idp -> createIdentityProvider(this.realm, this.baseURI, idp))
|
||||
.sorted(IDP_COMPARATOR_INSTANCE).toList();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -776,6 +776,48 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz
|
|||
Assert.assertFalse(loginPage.isSocialButtonPresent(org0Broker.getAlias()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDoNotShowBrokersIfOrganizationNotResolved() {
|
||||
String org0Name = "org-0";
|
||||
OrganizationResource org0 = testRealm().organizations().get(createOrganization(org0Name).getId());
|
||||
IdentityProviderRepresentation org0Broker = org0.identityProviders().getIdentityProviders().get(0);
|
||||
org0Broker.setHideOnLogin(false);
|
||||
org0Broker.getConfig().put(OrganizationModel.HIDE_IDP_ON_LOGIN_WHEN_ORGANIZATION_UNKNOWN, Boolean.TRUE.toString());
|
||||
org0Broker.getConfig().remove(OrganizationModel.ORGANIZATION_DOMAIN_ATTRIBUTE);
|
||||
testRealm().identityProviders().get(org0Broker.getAlias()).update(org0Broker);
|
||||
|
||||
// do not show if organization cannot be resolved
|
||||
oauth.clientId("broker-app");
|
||||
loginPage.open(bc.consumerRealmName());
|
||||
loginPage.loginUsername("user@unknowndomain.org");
|
||||
Assert.assertFalse(loginPage.isSocialButtonPresent(org0Broker.getAlias()));
|
||||
|
||||
// show if organization can be resolved
|
||||
loginPage.open(bc.consumerRealmName());
|
||||
loginPage.loginUsername("user@org-0.org");
|
||||
Assert.assertTrue(loginPage.isSocialButtonPresent(org0Broker.getAlias()));
|
||||
|
||||
// show if the config is set to false
|
||||
org0Broker.getConfig().put(OrganizationModel.HIDE_IDP_ON_LOGIN_WHEN_ORGANIZATION_UNKNOWN, Boolean.FALSE.toString());
|
||||
testRealm().identityProviders().get(org0Broker.getAlias()).update(org0Broker);
|
||||
loginPage.open(bc.consumerRealmName());
|
||||
loginPage.loginUsername("user@unknowndomain.org");
|
||||
Assert.assertTrue(loginPage.isSocialButtonPresent(org0Broker.getAlias()));
|
||||
loginPage.open(bc.consumerRealmName());
|
||||
loginPage.loginUsername("user@org-0.org");
|
||||
Assert.assertTrue(loginPage.isSocialButtonPresent(org0Broker.getAlias()));
|
||||
|
||||
// hide if hide on login is set to true
|
||||
org0Broker.setHideOnLogin(true);
|
||||
testRealm().identityProviders().get(org0Broker.getAlias()).update(org0Broker);
|
||||
loginPage.open(bc.consumerRealmName());
|
||||
loginPage.loginUsername("user@unknowndomain.org");
|
||||
Assert.assertFalse(loginPage.isSocialButtonPresent(org0Broker.getAlias()));
|
||||
loginPage.open(bc.consumerRealmName());
|
||||
loginPage.loginUsername("user@org-0.org");
|
||||
Assert.assertFalse(loginPage.isSocialButtonPresent(org0Broker.getAlias()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoginUsingBrokerWithoutDomain() {
|
||||
OrganizationResource organization = testRealm().organizations().get(createOrganization().getId());
|
||||
|
|
|
|||
Loading…
Reference in a new issue