Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 653e73b

Browse files
committedJul 23, 2024
#235 Add PhaseTwo changes
1 parent ccf9f1f commit 653e73b

File tree

3 files changed

+42
-3
lines changed

3 files changed

+42
-3
lines changed
 

‎src/main/java/io/phasetwo/service/auth/idp/HomeIdpDiscoveryAuthenticator.java

+23-2
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@
1313
import org.keycloak.models.AuthenticationExecutionModel;
1414
import org.keycloak.models.IdentityProviderModel;
1515
import org.keycloak.models.KeycloakSession;
16+
import org.keycloak.models.ModelDuplicateException;
1617
import org.keycloak.models.RealmModel;
1718
import org.keycloak.models.UserModel;
19+
import org.keycloak.models.utils.KeycloakModelUtils;
1820
import org.keycloak.services.managers.AuthenticationManager;
1921

2022
import java.util.List;
2123

24+
import static org.keycloak.protocol.oidc.OIDCLoginProtocol.LOGIN_HINT_PARAM;
2225
import static org.keycloak.services.validation.Validation.FIELD_USERNAME;
2326

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

107110
final List<IdentityProviderModel> homeIdps = context.discoverer(discovererConfig).discoverForUser(authenticationFlowContext, username);
108111
if (homeIdps.isEmpty()) {
109-
authenticationFlowContext.attempted();
110-
context.loginHint().setInAuthSession(username);
112+
if (authenticationFlowContext.getExecution().getRequirement() == AuthenticationExecutionModel.Requirement.REQUIRED) {
113+
authenticationFlowContext.success();
114+
} else {
115+
authenticationFlowContext.attempted();
116+
context.loginHint().setInAuthSession(username);
117+
}
111118
} else {
112119
RememberMe rememberMe = context.rememberMe();
113120
rememberMe.handleAction(formData);
@@ -117,6 +124,7 @@ public void action(AuthenticationFlowContext authenticationFlowContext) {
117124
}
118125

119126
private String setUserInContext(AuthenticationFlowContext context, String username) {
127+
context.clearUser();
120128
username = trimToNull(username);
121129

122130
if (username == null) {
@@ -130,6 +138,19 @@ private String setUserInContext(AuthenticationFlowContext context, String userna
130138
LOG.debugf("Found username '%s' in request", username);
131139
context.getEvent().detail(Details.USERNAME, username);
132140
context.getAuthenticationSession().setAuthNote(ATTEMPTED_USERNAME, username);
141+
context.getAuthenticationSession().setClientNote(LOGIN_HINT_PARAM, username);
142+
143+
try {
144+
UserModel user = KeycloakModelUtils.findUserByNameOrEmail(context.getSession(), context.getRealm(),
145+
username);
146+
if (user != null) {
147+
LOG.tracef("Setting user '%s' in context", user.getId());
148+
context.setUser(user);
149+
}
150+
} catch (ModelDuplicateException ex) {
151+
LOG.warnf(ex, "Could not uniquely identify the user. Multiple users with name or email '%s' found.",
152+
username);
153+
}
133154

134155
return username;
135156
}

‎src/main/java/io/phasetwo/service/auth/idp/discovery/email/EmailHomeIdpDiscoverer.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ private List<IdentityProviderModel> discoverHomeIdps(AuthenticationFlowContext c
9797
Collectors.toMap(FederatedIdentityModel::getIdentityProvider, FederatedIdentityModel::getUserName));
9898
}
9999

100+
101+
//Todo: This logic should be moved in a custom identity provider class. see OrgsIdentityProviders
100102
List<IdentityProviderModel> candidateIdps = identityProviders.candidatesForHomeIdp(context, user);
101103
if (candidateIdps == null) {
102104
candidateIdps = emptyList();
@@ -112,7 +114,7 @@ private List<IdentityProviderModel> discoverHomeIdps(AuthenticationFlowContext c
112114
OrganizationProvider orgs = context.getSession().getProvider(OrganizationProvider.class);
113115
List<IdentityProviderModel> idpsWithMatchingDomain =
114116
orgs.getOrganizationsStreamForDomain(
115-
context.getRealm(), domain.toString(), config.forwardUserWithUnverifiedEmail())
117+
context.getRealm(), domain.toString(), config.requireVerifiedDomain())
116118
.flatMap(OrganizationModel::getIdentityProvidersStream)
117119
.filter(IdentityProviderModel::isEnabled)
118120
.collect(Collectors.toList());

‎src/main/java/io/phasetwo/service/auth/idp/discovery/email/EmailHomeIdpDiscovererConfig.java

+16
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ final class EmailHomeIdpDiscovererConfig {
1616
private static final String FORWARD_TO_LINKED_IDP = "forwardToLinkedIdp";
1717
private static final String USER_ATTRIBUTE = "userAttribute";
1818
private static final String FORWARD_UNVERIFIED_ATTRIBUTE = "forwardUnverifiedEmail";
19+
static final String REQUIRE_VERIFIED_DOMAIN = "requireVerifiedDomain";
1920

2021
private static final ProviderConfigProperty FORWARD_TO_LINKED_IDP_PROPERTY = new ProviderConfigProperty(
2122
FORWARD_TO_LINKED_IDP,
@@ -41,10 +42,19 @@ final class EmailHomeIdpDiscovererConfig {
4142
false,
4243
false);
4344

45+
private static final ProviderConfigProperty REQUIRE_VERIFIED_DOMAIN_PROPERTY = new ProviderConfigProperty(
46+
REQUIRE_VERIFIED_DOMAIN,
47+
"Require a verified domain",
48+
"Whether a verified domain name for an organization is required to forward to their identity provider.",
49+
BOOLEAN_TYPE,
50+
false,
51+
false);
52+
4453
static final List<ProviderConfigProperty> CONFIG_PROPERTIES = ProviderConfigurationBuilder.create()
4554
.property(USER_ATTRIBUTE_PROPERTY)
4655
.property(FORWARD_UNVERIFIED_PROPERTY)
4756
.property(FORWARD_TO_LINKED_IDP_PROPERTY)
57+
.property(REQUIRE_VERIFIED_DOMAIN_PROPERTY)
4858
.build();
4959
private final AuthenticatorConfigModel authenticatorConfigModel;
5060

@@ -70,6 +80,12 @@ boolean forwardUserWithUnverifiedEmail() {
7080
.orElse(false);
7181
}
7282

83+
boolean requireVerifiedDomain() {
84+
return Optional.ofNullable(authenticatorConfigModel)
85+
.map(it -> Boolean.parseBoolean(it.getConfig().getOrDefault(REQUIRE_VERIFIED_DOMAIN, "false")))
86+
.orElse(false);
87+
}
88+
7389
String getAlias() {
7490
return Optional.ofNullable(authenticatorConfigModel)
7591
.map(AuthenticatorConfigModel::getAlias)

0 commit comments

Comments
 (0)
Please sign in to comment.