Skip to content

Commit

Permalink
#235 Add PhaseTwo changes
Browse files Browse the repository at this point in the history
  • Loading branch information
rtufisi committed Jul 22, 2024
1 parent ccf9f1f commit 1dcf464
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.services.managers.AuthenticationManager;

import java.util.List;

import static org.keycloak.protocol.oidc.OIDCLoginProtocol.LOGIN_HINT_PARAM;
import static org.keycloak.services.validation.Validation.FIELD_USERNAME;

final class HomeIdpDiscoveryAuthenticator extends AbstractUsernameFormAuthenticator {
Expand Down Expand Up @@ -106,8 +109,12 @@ public void action(AuthenticationFlowContext authenticationFlowContext) {

final List<IdentityProviderModel> homeIdps = context.discoverer(discovererConfig).discoverForUser(authenticationFlowContext, username);
if (homeIdps.isEmpty()) {
authenticationFlowContext.attempted();
context.loginHint().setInAuthSession(username);
if (authenticationFlowContext.getExecution().getRequirement() == AuthenticationExecutionModel.Requirement.REQUIRED) {
authenticationFlowContext.success();
} else {
authenticationFlowContext.attempted();
context.loginHint().setInAuthSession(username);
}
} else {
RememberMe rememberMe = context.rememberMe();
rememberMe.handleAction(formData);
Expand All @@ -117,6 +124,7 @@ public void action(AuthenticationFlowContext authenticationFlowContext) {
}

private String setUserInContext(AuthenticationFlowContext context, String username) {
context.clearUser();
username = trimToNull(username);

if (username == null) {
Expand All @@ -130,6 +138,19 @@ private String setUserInContext(AuthenticationFlowContext context, String userna
LOG.debugf("Found username '%s' in request", username);
context.getEvent().detail(Details.USERNAME, username);
context.getAuthenticationSession().setAuthNote(ATTEMPTED_USERNAME, username);
context.getAuthenticationSession().setClientNote(LOGIN_HINT_PARAM, username);

try {
UserModel user = KeycloakModelUtils.findUserByNameOrEmail(context.getSession(), context.getRealm(),
username);
if (user != null) {
LOG.tracef("Setting user '%s' in context", user.getId());
context.setUser(user);
}
} catch (ModelDuplicateException ex) {
LOG.warnf(ex, "Could not uniquely identify the user. Multiple users with name or email '%s' found.",
username);
}

return username;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ private List<IdentityProviderModel> discoverHomeIdps(AuthenticationFlowContext c
Collectors.toMap(FederatedIdentityModel::getIdentityProvider, FederatedIdentityModel::getUserName));
}


//Todo: This logic should be moved in a custom identity provider class. see OrgsIdentityProviders
List<IdentityProviderModel> candidateIdps = identityProviders.candidatesForHomeIdp(context, user);
if (candidateIdps == null) {
candidateIdps = emptyList();
Expand All @@ -112,7 +114,7 @@ private List<IdentityProviderModel> discoverHomeIdps(AuthenticationFlowContext c
OrganizationProvider orgs = context.getSession().getProvider(OrganizationProvider.class);
List<IdentityProviderModel> idpsWithMatchingDomain =
orgs.getOrganizationsStreamForDomain(
context.getRealm(), domain.toString(), config.forwardUserWithUnverifiedEmail())
context.getRealm(), domain.toString(), config.requireVerifiedDomain())
.flatMap(OrganizationModel::getIdentityProvidersStream)
.filter(IdentityProviderModel::isEnabled)
.collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ final class EmailHomeIdpDiscovererConfig {
private static final String FORWARD_TO_LINKED_IDP = "forwardToLinkedIdp";
private static final String USER_ATTRIBUTE = "userAttribute";
private static final String FORWARD_UNVERIFIED_ATTRIBUTE = "forwardUnverifiedEmail";
static final String REQUIRE_VERIFIED_DOMAIN = "requireVerifiedDomain";

private static final ProviderConfigProperty FORWARD_TO_LINKED_IDP_PROPERTY = new ProviderConfigProperty(
FORWARD_TO_LINKED_IDP,
Expand All @@ -41,10 +42,20 @@ final class EmailHomeIdpDiscovererConfig {
false,
false);

private static final ProviderConfigProperty REQUIRE_VERIFIED_DOMAIN_PROPERTY =
new ProviderConfigProperty(
REQUIRE_VERIFIED_DOMAIN,
"Require a verified domain",
"Whether a verified domain name for an organization is required to forward to their identity provider.",
BOOLEAN_TYPE,
false,
false);

static final List<ProviderConfigProperty> CONFIG_PROPERTIES = ProviderConfigurationBuilder.create()
.property(USER_ATTRIBUTE_PROPERTY)
.property(FORWARD_UNVERIFIED_PROPERTY)
.property(FORWARD_TO_LINKED_IDP_PROPERTY)
.property(REQUIRE_VERIFIED_DOMAIN_PROPERTY)
.build();
private final AuthenticatorConfigModel authenticatorConfigModel;

Expand All @@ -70,6 +81,14 @@ boolean forwardUserWithUnverifiedEmail() {
.orElse(false);
}

boolean requireVerifiedDomain() {
return Optional.ofNullable(authenticatorConfigModel)
.map(
it ->
Boolean.parseBoolean(it.getConfig().getOrDefault(REQUIRE_VERIFIED_DOMAIN, "false")))
.orElse(false);
}

String getAlias() {
return Optional.ofNullable(authenticatorConfigModel)
.map(AuthenticatorConfigModel::getAlias)
Expand Down

0 comments on commit 1dcf464

Please sign in to comment.