From e10811a24a20ed3d1e15f787bb0c470368ec8497 Mon Sep 17 00:00:00 2001 From: Sven-Torben Janus Date: Sat, 20 Apr 2024 13:10:04 +0200 Subject: [PATCH] feat: Support KC Organization Feature (DRAFT) This is just a rough draft - needs testing and refactorings. --- docker-compose.yml | 4 +- pom.xml | 2 +- ...tHomeIdpDiscoveryAuthenticatorFactory.java | 6 +- .../authentication/hidpd/OperationalInfo.java | 15 +++++ .../authentication/hidpd/Redirector.java | 13 +++-- .../email/EmailHomeIdpDiscoverer.java | 2 +- .../email/EmailHomeIdpDiscovererFactory.java | 10 +++- .../discovery/email/IdentityProviders.java | 3 +- .../orgs/domainhint/OrgsDomainDiscoverer.java | 44 ++++++++++++++ .../OrgsDomainDiscovererProviderFactory.java | 54 ++++++++++++++++++ ...nHomeIdpDiscoveryAuthenticatorFactory.java | 53 +++++++++++++++++ .../OrgsEmailHomeIdpDiscovererFactory.java | 48 ++++++++++++++++ ...lHomeIdpDiscoveryAuthenticatorFactory.java | 57 +++++++++++++++++++ .../orgs/email/OrgsIdentityProviders.java | 56 ++++++++++++++++++ ...dpd.discovery.spi.HomeIdpDiscovererFactory | 2 + ...ycloak.authentication.AuthenticatorFactory | 2 + 16 files changed, 355 insertions(+), 16 deletions(-) create mode 100644 src/main/java/de/sventorben/keycloak/authentication/hidpd/OperationalInfo.java create mode 100644 src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/domainhint/OrgsDomainDiscoverer.java create mode 100644 src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/domainhint/OrgsDomainDiscovererProviderFactory.java create mode 100644 src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/domainhint/OrgsDomainHomeIdpDiscoveryAuthenticatorFactory.java create mode 100644 src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/email/OrgsEmailHomeIdpDiscovererFactory.java create mode 100644 src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/email/OrgsEmailHomeIdpDiscoveryAuthenticatorFactory.java create mode 100644 src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/email/OrgsIdentityProviders.java diff --git a/docker-compose.yml b/docker-compose.yml index 69be7e5..d92e505 100755 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,14 +3,14 @@ services: keycloak: container_name: keycloak hostname: keycloak - image: quay.io/keycloak/keycloak:24.0.2 + image: quay.io/keycloak/keycloak:nightly environment: KEYCLOAK_ADMIN: admin KEYCLOAK_ADMIN_PASSWORD: admin DEBUG_PORT: '*:8787' DEBUG: 'true' - command: ['start-dev', '--debug', '--import-realm'] + command: ['start-dev', '--debug', '--import-realm', '--features=organization'] ports: - 8080:8080 - 8443:8443 diff --git a/pom.xml b/pom.xml index 8695673..247fd06 100644 --- a/pom.xml +++ b/pom.xml @@ -51,7 +51,7 @@ 17 - 24.0.2 + 999.0.0-SNAPSHOT ${version.keycloak} diff --git a/src/main/java/de/sventorben/keycloak/authentication/hidpd/AbstractHomeIdpDiscoveryAuthenticatorFactory.java b/src/main/java/de/sventorben/keycloak/authentication/hidpd/AbstractHomeIdpDiscoveryAuthenticatorFactory.java index 2c0e2cf..157a963 100644 --- a/src/main/java/de/sventorben/keycloak/authentication/hidpd/AbstractHomeIdpDiscoveryAuthenticatorFactory.java +++ b/src/main/java/de/sventorben/keycloak/authentication/hidpd/AbstractHomeIdpDiscoveryAuthenticatorFactory.java @@ -90,11 +90,7 @@ public final void close() { @Override public final Map getOperationalInfo() { - String version = getClass().getPackage().getImplementationVersion(); - if (version == null) { - version = "dev-snapshot"; - } - return Map.of("Version", version); + return OperationalInfo.get(); } /** diff --git a/src/main/java/de/sventorben/keycloak/authentication/hidpd/OperationalInfo.java b/src/main/java/de/sventorben/keycloak/authentication/hidpd/OperationalInfo.java new file mode 100644 index 0000000..022bc00 --- /dev/null +++ b/src/main/java/de/sventorben/keycloak/authentication/hidpd/OperationalInfo.java @@ -0,0 +1,15 @@ +package de.sventorben.keycloak.authentication.hidpd; + +import java.util.Map; + +public final class OperationalInfo { + + public static Map get() { + String version = OperationalInfo.class.getPackage().getImplementationVersion(); + if (version == null) { + version = "dev-snapshot"; + } + return Map.of("Version", version); + } + +} diff --git a/src/main/java/de/sventorben/keycloak/authentication/hidpd/Redirector.java b/src/main/java/de/sventorben/keycloak/authentication/hidpd/Redirector.java index 839d7c2..235f8d3 100755 --- a/src/main/java/de/sventorben/keycloak/authentication/hidpd/Redirector.java +++ b/src/main/java/de/sventorben/keycloak/authentication/hidpd/Redirector.java @@ -3,6 +3,7 @@ import jakarta.ws.rs.core.Response; import org.jboss.logging.Logger; import org.keycloak.authentication.AuthenticationFlowContext; +import org.keycloak.authentication.AuthenticationProcessor; import org.keycloak.broker.provider.AuthenticationRequest; import org.keycloak.broker.provider.IdentityProvider; import org.keycloak.broker.provider.IdentityProviderFactory; @@ -13,6 +14,7 @@ import org.keycloak.models.RealmModel; import org.keycloak.services.Urls; import org.keycloak.services.managers.ClientSessionCode; +import org.keycloak.services.resources.IdentityBrokerService; import org.keycloak.sessions.AuthenticationSessionModel; import static org.keycloak.services.resources.IdentityBrokerService.getIdentityProviderFactory; @@ -45,26 +47,27 @@ void redirectTo(IdentityProviderModel idp) { } new HomeIdpAuthenticationFlowContext(context).loginHint().copyTo(clientSessionCode); IdentityProviderFactory providerFactory = getIdentityProviderFactory(keycloakSession, idp); - IdentityProvider identityProvider = providerFactory.create(keycloakSession, idp); + IdentityProvider identityProvider = providerFactory.create(keycloakSession, idp); - Response response = identityProvider.performLogin(createAuthenticationRequest(providerAlias, clientSessionCode)); + Response response = identityProvider.performLogin(createAuthenticationRequest(providerAlias, identityProvider, clientSessionCode)); context.forceChallenge(response); } - private AuthenticationRequest createAuthenticationRequest(String providerId, ClientSessionCode clientSessionCode) { + private AuthenticationRequest createAuthenticationRequest(String providerAlias, IdentityProvider identityProvider, ClientSessionCode clientSessionCode) { AuthenticationSessionModel authSession = null; IdentityBrokerState encodedState = null; if (clientSessionCode != null) { authSession = clientSessionCode.getClientSession(); String relayState = clientSessionCode.getOrGenerateCode(); - encodedState = IdentityBrokerState.decoded(relayState, authSession.getClient().getId(), authSession.getClient().getClientId(), authSession.getTabId()); + String clientData = identityProvider.supportsLongStateParameter() ? AuthenticationProcessor.getClientData(context.getSession(), authSession) : null; + encodedState = IdentityBrokerState.decoded(relayState, authSession.getClient().getId(), authSession.getClient().getClientId(), authSession.getTabId(), clientData); } KeycloakSession keycloakSession = context.getSession(); KeycloakUriInfo keycloakUriInfo = keycloakSession.getContext().getUri(); RealmModel realm = context.getRealm(); - String redirectUri = Urls.identityProviderAuthnResponse(keycloakUriInfo.getBaseUri(), providerId, realm.getName()).toString(); + String redirectUri = Urls.identityProviderAuthnResponse(keycloakUriInfo.getBaseUri(), providerAlias, realm.getName()).toString(); return new AuthenticationRequest(keycloakSession, realm, authSession, context.getHttpRequest(), keycloakUriInfo, encodedState, redirectUri); } diff --git a/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/email/EmailHomeIdpDiscoverer.java b/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/email/EmailHomeIdpDiscoverer.java index 6645d0e..f5ac893 100644 --- a/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/email/EmailHomeIdpDiscoverer.java +++ b/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/email/EmailHomeIdpDiscoverer.java @@ -84,7 +84,7 @@ private List discoverHomeIdps(AuthenticationFlowContext c Collectors.toMap(FederatedIdentityModel::getIdentityProvider, FederatedIdentityModel::getUserName)); } - List candidateIdps = identityProviders.candidatesForHomeIdp(context); + List candidateIdps = identityProviders.candidatesForHomeIdp(context, user); if (candidateIdps == null) { candidateIdps = emptyList(); } diff --git a/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/email/EmailHomeIdpDiscovererFactory.java b/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/email/EmailHomeIdpDiscovererFactory.java index 082677c..25c3b2f 100644 --- a/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/email/EmailHomeIdpDiscovererFactory.java +++ b/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/email/EmailHomeIdpDiscovererFactory.java @@ -6,8 +6,11 @@ import org.keycloak.Config; import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; +import org.keycloak.provider.ServerInfoAwareProviderFactory; -public final class EmailHomeIdpDiscovererFactory implements HomeIdpDiscovererFactory { +import java.util.Map; + +public final class EmailHomeIdpDiscovererFactory implements HomeIdpDiscovererFactory, ServerInfoAwareProviderFactory { static final String PROVIDER_ID = "email"; @@ -35,4 +38,9 @@ public void close() { public String getId() { return PROVIDER_ID; } + + @Override + public Map getOperationalInfo() { + return ServInf; + } } diff --git a/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/email/IdentityProviders.java b/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/email/IdentityProviders.java index 137157c..439f7d6 100644 --- a/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/email/IdentityProviders.java +++ b/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/email/IdentityProviders.java @@ -5,6 +5,7 @@ import org.keycloak.authentication.AuthenticationFlowContext; import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.RealmModel; +import org.keycloak.models.UserModel; import java.util.List; import java.util.stream.Collectors; @@ -50,7 +51,7 @@ public interface IdentityProviders { * current authentication process. * @return A list of {@link IdentityProviderModel} from the realm. May be empty but not {@code null}. */ - default List candidatesForHomeIdp(AuthenticationFlowContext context) { + default List candidatesForHomeIdp(AuthenticationFlowContext context, UserModel user) { RealmModel realm = context.getRealm(); List enabledIdps = realm.getIdentityProvidersStream() .filter(IdentityProviderModel::isEnabled) diff --git a/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/domainhint/OrgsDomainDiscoverer.java b/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/domainhint/OrgsDomainDiscoverer.java new file mode 100644 index 0000000..3db210b --- /dev/null +++ b/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/domainhint/OrgsDomainDiscoverer.java @@ -0,0 +1,44 @@ +package de.sventorben.keycloak.authentication.hidpd.discovery.orgs.domainhint; + +import de.sventorben.keycloak.authentication.hidpd.discovery.spi.HomeIdpDiscoverer; +import org.keycloak.authentication.AuthenticationFlowContext; +import org.keycloak.models.IdentityProviderModel; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.OrganizationModel; +import org.keycloak.organization.OrganizationProvider; + +import java.util.Collections; +import java.util.List; + +final class OrgsDomainDiscoverer implements HomeIdpDiscoverer { + + private final KeycloakSession keycloakSession; + + OrgsDomainDiscoverer(KeycloakSession keycloakSession) { + this.keycloakSession = keycloakSession; + } + + @Override + public List discoverForUser(AuthenticationFlowContext context, String username) { + String domain = username; + OrganizationProvider orgProvider = keycloakSession.getProvider(OrganizationProvider.class); + + if (!orgProvider.isEnabled()) { + return Collections.emptyList(); + } + + OrganizationModel org = orgProvider.getByDomainName(domain); + if (org != null) { + IdentityProviderModel idp = org.getIdentityProvider(); + if (idp != null) { + return Collections.singletonList(idp); + } + } + return Collections.emptyList(); + } + + @Override + public void close() { + + } +} diff --git a/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/domainhint/OrgsDomainDiscovererProviderFactory.java b/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/domainhint/OrgsDomainDiscovererProviderFactory.java new file mode 100644 index 0000000..725b99a --- /dev/null +++ b/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/domainhint/OrgsDomainDiscovererProviderFactory.java @@ -0,0 +1,54 @@ +package de.sventorben.keycloak.authentication.hidpd.discovery.orgs.domainhint; + +import de.sventorben.keycloak.authentication.hidpd.OperationalInfo; +import de.sventorben.keycloak.authentication.hidpd.discovery.spi.HomeIdpDiscoverer; +import de.sventorben.keycloak.authentication.hidpd.discovery.spi.HomeIdpDiscovererFactory; +import org.keycloak.Config; +import org.keycloak.common.Profile; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.KeycloakSessionFactory; +import org.keycloak.provider.EnvironmentDependentProviderFactory; +import org.keycloak.provider.ServerInfoAwareProviderFactory; + +import java.util.Map; + +public final class OrgsDomainDiscovererProviderFactory implements HomeIdpDiscovererFactory, EnvironmentDependentProviderFactory, ServerInfoAwareProviderFactory { + + private static final String PROVIDER_ID = "orgs-domain"; + + @Override + public boolean isSupported(Config.Scope config) { + return Profile.isFeatureEnabled(Profile.Feature.ORGANIZATION); + } + + @Override + public HomeIdpDiscoverer create(KeycloakSession keycloakSession) { + return new OrgsDomainDiscoverer(keycloakSession); + } + + @Override + public void init(Config.Scope scope) { + + } + + @Override + public void postInit(KeycloakSessionFactory keycloakSessionFactory) { + + } + + @Override + public void close() { + + } + + @Override + public String getId() { + return PROVIDER_ID; + } + + @Override + public final Map getOperationalInfo() { + return OperationalInfo.get(); + } + +} diff --git a/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/domainhint/OrgsDomainHomeIdpDiscoveryAuthenticatorFactory.java b/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/domainhint/OrgsDomainHomeIdpDiscoveryAuthenticatorFactory.java new file mode 100644 index 0000000..47e60dd --- /dev/null +++ b/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/domainhint/OrgsDomainHomeIdpDiscoveryAuthenticatorFactory.java @@ -0,0 +1,53 @@ +package de.sventorben.keycloak.authentication.hidpd.discovery.orgs.domainhint; + +import de.sventorben.keycloak.authentication.hidpd.AbstractHomeIdpDiscoveryAuthenticatorFactory; +import org.keycloak.Config; +import org.keycloak.common.Profile; +import org.keycloak.provider.EnvironmentDependentProviderFactory; +import org.keycloak.provider.ProviderConfigProperty; + +import java.util.Collections; +import java.util.List; + +public final class OrgsDomainHomeIdpDiscoveryAuthenticatorFactory extends AbstractHomeIdpDiscoveryAuthenticatorFactory implements EnvironmentDependentProviderFactory { + private static final String PROVIDER_ID = "orgs-domain"; + + @Override + public boolean isSupported(Config.Scope config) { + return Profile.isFeatureEnabled(Profile.Feature.ORGANIZATION); + } + + public OrgsDomainHomeIdpDiscoveryAuthenticatorFactory() { + super(new DiscovererConfig() { + @Override + public List getProperties() { + return Collections.emptyList(); + } + + @Override + public String getProviderId() { + return PROVIDER_ID; + } + }); + } + + @Override + public String getId() { + return PROVIDER_ID; + } + + @Override + public String getDisplayType() { + return "Home IdP Discovery - Organization via Domain Hint"; + } + + @Override + public String getReferenceCategory() { + return null; + } + + @Override + public String getHelpText() { + return "Redirects users to their organization's identity provider which will be discovered based on a domain hint"; + } +} diff --git a/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/email/OrgsEmailHomeIdpDiscovererFactory.java b/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/email/OrgsEmailHomeIdpDiscovererFactory.java new file mode 100644 index 0000000..3db1799 --- /dev/null +++ b/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/email/OrgsEmailHomeIdpDiscovererFactory.java @@ -0,0 +1,48 @@ +package de.sventorben.keycloak.authentication.hidpd.discovery.orgs.email; + +import de.sventorben.keycloak.authentication.hidpd.OperationalInfo; +import de.sventorben.keycloak.authentication.hidpd.Users; +import de.sventorben.keycloak.authentication.hidpd.discovery.email.EmailHomeIdpDiscoverer; +import de.sventorben.keycloak.authentication.hidpd.discovery.spi.HomeIdpDiscoverer; +import de.sventorben.keycloak.authentication.hidpd.discovery.spi.HomeIdpDiscovererFactory; +import org.keycloak.Config; +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.KeycloakSessionFactory; +import org.keycloak.provider.ServerInfoAwareProviderFactory; + +import java.util.Map; + +public final class OrgsEmailHomeIdpDiscovererFactory implements HomeIdpDiscovererFactory, ServerInfoAwareProviderFactory { + + static final String PROVIDER_ID = "orgs-email"; + + @Override + public HomeIdpDiscoverer create(KeycloakSession keycloakSession) { + return new EmailHomeIdpDiscoverer(new Users(keycloakSession), new OrgsIdentityProviders()); + } + + @Override + public void init(Config.Scope scope) { + + } + + @Override + public void postInit(KeycloakSessionFactory keycloakSessionFactory) { + + } + + @Override + public void close() { + + } + + @Override + public String getId() { + return PROVIDER_ID; + } + + @Override + public final Map getOperationalInfo() { + return OperationalInfo.get(); + } +} diff --git a/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/email/OrgsEmailHomeIdpDiscoveryAuthenticatorFactory.java b/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/email/OrgsEmailHomeIdpDiscoveryAuthenticatorFactory.java new file mode 100644 index 0000000..020a8ce --- /dev/null +++ b/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/email/OrgsEmailHomeIdpDiscoveryAuthenticatorFactory.java @@ -0,0 +1,57 @@ +package de.sventorben.keycloak.authentication.hidpd.discovery.orgs.email; + +import de.sventorben.keycloak.authentication.hidpd.AbstractHomeIdpDiscoveryAuthenticatorFactory; +import de.sventorben.keycloak.authentication.hidpd.OperationalInfo; +import org.keycloak.Config; +import org.keycloak.common.Profile; +import org.keycloak.provider.EnvironmentDependentProviderFactory; +import org.keycloak.provider.ProviderConfigProperty; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public final class OrgsEmailHomeIdpDiscoveryAuthenticatorFactory extends AbstractHomeIdpDiscoveryAuthenticatorFactory implements EnvironmentDependentProviderFactory { + + private static final String PROVIDER_ID = "orgs-email"; + + @Override + public boolean isSupported(Config.Scope config) { + return Profile.isFeatureEnabled(Profile.Feature.ORGANIZATION); + } + + public OrgsEmailHomeIdpDiscoveryAuthenticatorFactory() { + super(new DiscovererConfig() { + @Override + public List getProperties() { + return Collections.emptyList(); + } + + @Override + public String getProviderId() { + return PROVIDER_ID; + } + }); + } + + @Override + public String getId() { + return PROVIDER_ID; + } + + @Override + public String getDisplayType() { + return "Home IdP Discovery - Organization via Email"; + } + + @Override + public String getReferenceCategory() { + return null; + } + + @Override + public String getHelpText() { + return "Redirects users to their organization's identity provider which will be discovered based on the domain of the user's email address."; + } + +} diff --git a/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/email/OrgsIdentityProviders.java b/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/email/OrgsIdentityProviders.java new file mode 100644 index 0000000..e525578 --- /dev/null +++ b/src/main/java/de/sventorben/keycloak/authentication/hidpd/discovery/orgs/email/OrgsIdentityProviders.java @@ -0,0 +1,56 @@ +package de.sventorben.keycloak.authentication.hidpd.discovery.orgs.email; + +import de.sventorben.keycloak.authentication.hidpd.discovery.email.Domain; +import de.sventorben.keycloak.authentication.hidpd.discovery.email.IdentityProviders; +import org.keycloak.authentication.AuthenticationFlowContext; +import org.keycloak.models.IdentityProviderModel; +import org.keycloak.models.OrganizationModel; +import org.keycloak.models.UserModel; +import org.keycloak.organization.OrganizationProvider; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +final class OrgsIdentityProviders implements IdentityProviders { + + @Override + public List candidatesForHomeIdp(AuthenticationFlowContext context, UserModel user) { + OrganizationProvider orgProvider = context.getSession().getProvider(OrganizationProvider.class); + if (user == null) { + return Collections.emptyList(); + } + if (orgProvider.isEnabled()) { + OrganizationModel org = orgProvider.getByMember(user); + if (org != null) { + IdentityProviderModel orgIdp = org.getIdentityProvider(); + if (orgIdp != null) { + return Collections.singletonList(orgIdp); + } + } + } else { + // TODO: Log a warning + } + return Collections.emptyList(); + } + + @Override + public List withMatchingDomain(AuthenticationFlowContext context, List candidates, Domain domain) { + OrganizationProvider orgProvider = context.getSession().getProvider(OrganizationProvider.class); + if (orgProvider.isEnabled()) { + OrganizationModel org = orgProvider.getByDomainName(domain.getRawValue()); + if (org != null) { + IdentityProviderModel orgIdp = org.getIdentityProvider(); + if (orgIdp != null) { + List result = new ArrayList<>(candidates); + result.add(orgIdp); + return result; + } + } + } else { + // TODO: Log a warning + } + return candidates; + } + +} diff --git a/src/main/resources/META-INF/services/de.sventorben.keycloak.authentication.hidpd.discovery.spi.HomeIdpDiscovererFactory b/src/main/resources/META-INF/services/de.sventorben.keycloak.authentication.hidpd.discovery.spi.HomeIdpDiscovererFactory index bb355d9..09aaf87 100644 --- a/src/main/resources/META-INF/services/de.sventorben.keycloak.authentication.hidpd.discovery.spi.HomeIdpDiscovererFactory +++ b/src/main/resources/META-INF/services/de.sventorben.keycloak.authentication.hidpd.discovery.spi.HomeIdpDiscovererFactory @@ -1 +1,3 @@ de.sventorben.keycloak.authentication.hidpd.discovery.email.EmailHomeIdpDiscovererFactory +de.sventorben.keycloak.authentication.hidpd.discovery.orgs.domainhint.OrgsDomainDiscovererProviderFactory +de.sventorben.keycloak.authentication.hidpd.discovery.orgs.email.OrgsEmailHomeIdpDiscovererFactory diff --git a/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory b/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory index 28772e5..eb4380e 100755 --- a/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory +++ b/src/main/resources/META-INF/services/org.keycloak.authentication.AuthenticatorFactory @@ -1 +1,3 @@ de.sventorben.keycloak.authentication.hidpd.HomeIdpDiscoveryAuthenticatorFactory +de.sventorben.keycloak.authentication.hidpd.discovery.orgs.email.OrgsEmailHomeIdpDiscoveryAuthenticatorFactory +de.sventorben.keycloak.authentication.hidpd.discovery.orgs.domainhint.OrgsDomainHomeIdpDiscoveryAuthenticatorFactory