- * Implementors of this class need to provide their own {@link DiscovererConfig}, which includes - * the discovery logic specifics and configuration properties. This approach ensures flexibility and - * customizability, enabling developers to tailor the identity provider discovery process to specific - * organizational needs or authentication scenarios. - *
- *- * By inheriting from this class, developers can focus on the specifics of their discovery logic - * without worrying about the boilerplate associated with UI integration and redirection logic. - *
- * - * @apiNote This interface is part of the public API, but is currently unstable and may change in future releases. - * - * @see HomeIdpDiscoverer - * @see DiscovererConfig - */ -@PublicAPI(unstable = true) -public abstract class AbstractHomeIdpDiscoveryAuthenticatorFactory implements AuthenticatorFactory, ServerInfoAwareProviderFactory { - private static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = new AuthenticationExecutionModel.Requirement[]{REQUIRED, ALTERNATIVE, DISABLED}; - - private final DiscovererConfig discovererConfig; - - protected AbstractHomeIdpDiscoveryAuthenticatorFactory(DiscovererConfig discovererConfig) { - this.discovererConfig = discovererConfig; - } - - @Override - public final boolean isConfigurable() { - return true; - } - - @Override - public final AuthenticationExecutionModel.Requirement[] getRequirementChoices() { - return REQUIREMENT_CHOICES; - } - - @Override - public final boolean isUserSetupAllowed() { - return false; - } - - @Override - public final ListElements marked with this annotation are considered stable and safe for use in production - * environments, unless specified otherwise by the {@code unstable} attribute. Developers - * using these APIs can expect them to follow semantically versioned paths for updates, - * including deprecations and removals.
- * - *- * Unstable APIs are intended for early - * access to features for feedback and may change based on that feedback or - * be removed in future versions. - *
- *- * Default value: {@code false}, meaning the API is stable. - *
- * - * @return {@code true} if the API is unstable, {@code false} if it is stable. - */ - boolean unstable() default false; -} diff --git a/src/main/java/io/phasetwo/service/auth/idp/Reauthentication.java b/src/main/java/io/phasetwo/service/auth/idp/Reauthentication.java deleted file mode 100644 index 27551665..00000000 --- a/src/main/java/io/phasetwo/service/auth/idp/Reauthentication.java +++ /dev/null @@ -1,26 +0,0 @@ -//package de.sventorben.keycloak.authentication.hidpd; -package io.phasetwo.service.auth.idp; - -import org.keycloak.authentication.AuthenticationFlowContext; -import org.keycloak.models.UserSessionModel; -import org.keycloak.protocol.LoginProtocol; -import org.keycloak.services.managers.AuthenticationManager; - -final class Reauthentication { - - private final AuthenticationFlowContext context; - - Reauthentication(AuthenticationFlowContext context) { - this.context = context; - } - - boolean required() { - AuthenticationManager.AuthResult authResult = AuthenticationManager.authenticateIdentityCookie(context.getSession(), context.getRealm(), true); - UserSessionModel userSessionModel = null; - if (authResult != null) { - userSessionModel = authResult.getSession(); - } - LoginProtocol protocol = context.getSession().getProvider(LoginProtocol.class, context.getAuthenticationSession().getProtocol()); - return protocol.requireReauthentication(userSessionModel, context.getAuthenticationSession()); - } -} diff --git a/src/main/java/io/phasetwo/service/auth/idp/Redirector.java b/src/main/java/io/phasetwo/service/auth/idp/Redirector.java deleted file mode 100755 index 1283017a..00000000 --- a/src/main/java/io/phasetwo/service/auth/idp/Redirector.java +++ /dev/null @@ -1,74 +0,0 @@ -//package de.sventorben.keycloak.authentication.hidpd; -package io.phasetwo.service.auth.idp; - -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; -import org.keycloak.broker.provider.util.IdentityBrokerState; -import org.keycloak.models.IdentityProviderModel; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.KeycloakUriInfo; -import org.keycloak.models.RealmModel; -import org.keycloak.services.Urls; -import org.keycloak.services.managers.ClientSessionCode; -import org.keycloak.sessions.AuthenticationSessionModel; - -import static org.keycloak.services.resources.IdentityBrokerService.getIdentityProviderFactory; - -final class Redirector { - - private static final Logger LOG = Logger.getLogger(Redirector.class); - - private final AuthenticationFlowContext context; - - Redirector(AuthenticationFlowContext context) { - this.context = context; - } - - void redirectTo(IdentityProviderModel idp) { - String providerAlias = idp.getAlias(); - RealmModel realm = context.getRealm(); - AuthenticationSessionModel authenticationSession = context.getAuthenticationSession(); - KeycloakSession keycloakSession = context.getSession(); - ClientSessionCode- * Implementations of this interface should provide logic to filter identity providers based on - * custom criteria such as the domain associated with the user or other relevant factors. - *
- * - * @apiNote This interface is part of the public API but is marked as unstable and may be subject - * to changes in future releases. - */ -@PublicAPI(unstable = true) -public interface IdentityProviders { - - Logger LOG = Logger.getLogger(IdentityProviders.class); - - /** - * Filters the given list of identity provider candidates to return those that match a specified - * domain within the context of an authentication flow. - * - * @param context The authentication flow context providing runtime information about the - * current authentication process. - * @param candidates A list of potentially eligible identity providers that may be suitable - * for the user based on initial criteria (see {@code #candidatesForHomeIdp}). - * @param domain The domain criteria used to match identity providers. - * @return A filtered list of {@link IdentityProviderModel} that match the specified domain criteria. - * May be empty but not {@code null}. - */ - List- * This default method filters out and collects only those providers that are enabled. - *
- * @param context The authentication flow context providing runtime information about the - * current authentication process. - * @return A list of {@link IdentityProviderModel} from the realm. May be empty but not {@code null}. - */ - default List- * Implementations of this interface should provide the logic to determine the appropriate - * Home IdP(s) for a user, potentially based on attributes such as the username, domain, or - * other identifiers associated with the user's account. This is particularly useful in - * scenarios where users may belong to different IdPs based on their organization, domain, - * or other factors, and an automated method is required to direct the user to their - * respective IdP for authentication. - *
- * - * @apiNote This interface is part of the public API, but is currently unstable and may change in future releases. - * - * @see IdentityProviderModel - * @see AuthenticationFlowContext - */ -@PublicAPI(unstable = true) -public interface HomeIdpDiscoverer extends Provider { - - /** - * Discovers and returns a list of {@link IdentityProviderModel} instances representing - * the Home Identity Provider(s) for the specified user. The method takes the username - * of the user as a parameter and returns a list of IdP models that are considered the - * user's home IdPs. If no home IdP is found for the user, this method may return an - * empty list. - *- * Implementors should ensure that the logic for discovering the home IdPs is efficient - * and accounts for various criteria that may determine the user's Home IdP(s). The - * criteria and the discovery logic are dependent on the specific implementation. - *
- * @param context the {@link AuthenticationFlowContext} providing the current state and parameters - * of the authentication flow. This context can include various details such as the - * client, session, and other relevant information that can be utilized to determine - * the most appropriate home IdP(s) for the user. Implementors can use this context - * to access additional attributes or perform more complex logic based on the current - * authentication flow. - * @param username the unvalidated username provided by the user, serving as the primary identifier - * for the discovery of the user's Home IdP(s). Given that this username is unvalidated - * input, implementors should apply appropriate validation or sanitization measures - * to mitigate potential security risks or logic errors. This consideration is - * crucial, especially in scenarios where multiple users across different realms or - * IdPs might share the same username, necessitating the use of the authentication - * flow context to resolve such ambiguities. - * @return a list of {@link IdentityProviderModel} instances representing the discovered - * home IdP(s) for the user. The list may be empty if no home IdP is associated - * with the user. Do not return {@code null}. - */ - ListLicense: MIT https://github.com/sventorben/keycloak-home-idp-discovery/blob/main/LICENSE.md - * - *
Includes patches for loading from ATTEMPTED_USERNAME and looking up IdPs by an organization - * domains table. - * - *
Forked on September 4, 2023 from 04b9becfb37df63784559c936f0b49609686439e - */ -package io.phasetwo.service.auth.idp; diff --git a/src/main/resources/theme-resources/templates/hidpd-select-idp.ftl b/src/main/resources/theme-resources/templates/hidpd-select-idp.ftl deleted file mode 100644 index 8523f9cc..00000000 --- a/src/main/resources/theme-resources/templates/hidpd-select-idp.ftl +++ /dev/null @@ -1,28 +0,0 @@ -<#import "template.ftl" as layout> -<@layout.registrationLayout displayMessage=!messagesPerField.existsError('username') displayInfo=(realm.password && realm.registrationAllowed && !registrationDisabled??); section> - <#if section = "header"> - ${msg("loginAccountTitle")} - <#elseif section = "socialProviders" > - <#if realm.password && hidpd.providers??> -
- #if> - #if> - -@layout.registrationLayout> diff --git a/src/test/java/io/phasetwo/service/AbstractCypressOrganizationTest.java b/src/test/java/io/phasetwo/service/AbstractCypressOrganizationTest.java index 24700fb8..bb4eb083 100644 --- a/src/test/java/io/phasetwo/service/AbstractCypressOrganizationTest.java +++ b/src/test/java/io/phasetwo/service/AbstractCypressOrganizationTest.java @@ -55,11 +55,20 @@ public class AbstractCypressOrganizationTest { "io.phasetwo.keycloak:keycloak-events" }; + static final String[] internalDeps = { + "lib/keycloak-home-idp-discovery.jar" + }; + static List