Allow auto-redirect existing users federated from organization broker when using the username

Closes #30746

Signed-off-by: Martin Kanis <mkanis@redhat.com>
This commit is contained in:
Martin Kanis 2024-07-12 14:56:25 +02:00 committed by Pedro Igor
parent 1864cf1827
commit 887db25f00
5 changed files with 48 additions and 23 deletions

View file

@ -73,22 +73,35 @@ public class OrganizationAuthenticator extends IdentityProviderAuthenticator {
String username = parameters.getFirst(UserModel.USERNAME); String username = parameters.getFirst(UserModel.USERNAME);
String emailDomain = getEmailDomain(username); String emailDomain = getEmailDomain(username);
RealmModel realm = context.getRealm();
OrganizationProvider provider = getOrganizationProvider();
OrganizationModel organization = null;
UserModel user = null;
if (emailDomain == null) { if (emailDomain == null) {
// username does not map to any email domain, go to the next authentication step/sub-flow // username was provided, check if the user is already federated in the realm and onboarded in an organization
user = session.users().getUserByUsername(realm, username);
if (user != null) {
organization = getOrganizationProvider().getByMember(user);
}
if (organization == null) {
// user in not member of an organization, go to the next authentication step/sub-flow
context.attempted(); context.attempted();
return; return;
} }
} else {
OrganizationProvider provider = getOrganizationProvider(); organization = provider.getByDomainName(emailDomain);
OrganizationModel organization = provider.getByDomainName(emailDomain); }
if (organization != null) { if (organization != null) {
// make sure the organization is set to the session to make it available to templates // make sure the organization is set to the session to make it available to templates
session.setAttribute(OrganizationModel.class.getName(), organization); session.setAttribute(OrganizationModel.class.getName(), organization);
} }
RealmModel realm = context.getRealm(); if (user == null) {
UserModel user = session.users().getUserByEmail(realm, username); user = session.users().getUserByEmail(realm, username);
}
if (user != null) { if (user != null) {
// user exists, check if enabled // user exists, check if enabled
@ -100,8 +113,9 @@ public class OrganizationAuthenticator extends IdentityProviderAuthenticator {
context.setUser(user); context.setUser(user);
if (organization != null) { if (organization != null) {
OrganizationBean orgBean = new OrganizationBean(session, organization, user);
context.form().setAttributeMapper(attributes -> { context.form().setAttributeMapper(attributes -> {
attributes.put("org", new OrganizationBean(session, organization, user)); attributes.put("org", orgBean);
return attributes; return attributes;
}); });
} }

View file

@ -67,7 +67,7 @@ public class OrganizationAccountTest extends AbstractOrganizationTest {
public void testFailUnlinkIdentityProvider() throws IOException { public void testFailUnlinkIdentityProvider() throws IOException {
// federate user // federate user
OrganizationResource organization = testRealm().organizations().get(createOrganization().getId()); OrganizationResource organization = testRealm().organizations().get(createOrganization().getId());
assertBrokerRegistration(organization, bc.getUserEmail()); assertBrokerRegistration(organization, bc.getUserLogin(), bc.getUserEmail());
// reset password to obtain a token and access the account api // reset password to obtain a token and access the account api
UserRepresentation user = testRealm().users().searchByEmail(bc.getUserEmail(), true).get(0); UserRepresentation user = testRealm().users().searchByEmail(bc.getUserEmail(), true).get(0);
ApiUtil.resetUserPassword(realmsResouce().realm(bc.consumerRealmName()).users().get(user.getId()), bc.getUserPassword(), false); ApiUtil.resetUserPassword(realmsResouce().realm(bc.consumerRealmName()).users().get(user.getId()), bc.getUserPassword(), false);

View file

@ -183,11 +183,11 @@ public abstract class AbstractOrganizationTest extends AbstractAdminTest {
} }
} }
protected void assertBrokerRegistration(OrganizationResource organization, String email) { protected void assertBrokerRegistration(OrganizationResource organization, String username, String email) {
// login with email only // login with email only
openIdentityFirstLoginPage(email, true, null, false, false); openIdentityFirstLoginPage(email, true, null, false, false);
loginOrgIdp(email, email, true, true); loginOrgIdp(username, email, true, true);
assertIsMember(email, organization); assertIsMember(email, organization);
} }

View file

@ -53,7 +53,7 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz
@Test @Test
public void testRegistrationRedirectWhenSingleBroker() { public void testRegistrationRedirectWhenSingleBroker() {
OrganizationResource organization = testRealm().organizations().get(createOrganization().getId()); OrganizationResource organization = testRealm().organizations().get(createOrganization().getId());
assertBrokerRegistration(organization, bc.getUserEmail()); assertBrokerRegistration(organization, bc.getUserLogin(), bc.getUserEmail());
} }
@Test @Test
@ -276,16 +276,27 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz
OrganizationResource organization = testRealm().organizations().get(createOrganization().getId()); OrganizationResource organization = testRealm().organizations().get(createOrganization().getId());
// add the member for the first time // add the member for the first time
assertBrokerRegistration(organization, bc.getUserEmail()); assertBrokerRegistration(organization, bc.getUserLogin(), bc.getUserEmail());
// logout to force the user to authenticate again // logout to force the user to authenticate again
UserRepresentation account = getUserRepresentation(bc.getUserEmail()); UserRepresentation account = getUserRepresentation(bc.getUserEmail());
realmsResouce().realm(bc.consumerRealmName()).users().get(account.getId()).logout(); realmsResouce().realm(bc.consumerRealmName()).users().get(account.getId()).logout();
realmsResouce().realm(bc.providerRealmName()).logoutAll(); realmsResouce().realm(bc.providerRealmName()).logoutAll();
openIdentityFirstLoginPage(bc.getUserLogin(), true, null, false, false);
// login to the organization identity provider by username and automatically redirects to the app as the account already exists
loginPage.login(bc.getUserLogin(), bc.getUserPassword());
appPage.assertCurrent();
assertIsMember(bc.getUserEmail(), organization);
// logout to force the user to authenticate again
realmsResouce().realm(bc.consumerRealmName()).users().get(account.getId()).logout();
realmsResouce().realm(bc.providerRealmName()).logoutAll();
openIdentityFirstLoginPage(bc.getUserEmail(), true, null, false, false); openIdentityFirstLoginPage(bc.getUserEmail(), true, null, false, false);
// login to the organization identity provider and automatically redirects to the app as the account already exists // login to the organization identity provider by email and automatically redirects to the app as the account already exists
loginPage.login(bc.getUserEmail(), bc.getUserPassword()); loginPage.login(bc.getUserEmail(), bc.getUserPassword());
appPage.assertCurrent(); appPage.assertCurrent();
assertIsMember(bc.getUserEmail(), organization); assertIsMember(bc.getUserEmail(), organization);
@ -316,7 +327,7 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz
brokerRep.getConfig().put(IdentityProviderRedirectMode.EMAIL_MATCH.getKey(), Boolean.TRUE.toString()); brokerRep.getConfig().put(IdentityProviderRedirectMode.EMAIL_MATCH.getKey(), Boolean.TRUE.toString());
testRealm().identityProviders().get(brokerRep.getAlias()).update(brokerRep); testRealm().identityProviders().get(brokerRep.getAlias()).update(brokerRep);
assertBrokerRegistration(organization, email); assertBrokerRegistration(organization, bc.getUserLogin(), email);
// logout to force the user to authenticate again // logout to force the user to authenticate again
UserRepresentation account = getUserRepresentation(email); UserRepresentation account = getUserRepresentation(email);
@ -349,7 +360,7 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz
testRealm().identityProviders().get(idpRep.getAlias()).update(idpRep); testRealm().identityProviders().get(idpRep.getAlias()).update(idpRep);
// add the member for the first time // add the member for the first time
assertBrokerRegistration(organization, bc.getUserEmail()); assertBrokerRegistration(organization, bc.getUserLogin(), bc.getUserEmail());
UserRepresentation member = getUserRepresentation(bc.getUserEmail()); UserRepresentation member = getUserRepresentation(bc.getUserEmail());
member.setEmail(KeycloakModelUtils.generateId() + "@user.org"); member.setEmail(KeycloakModelUtils.generateId() + "@user.org");
@ -373,7 +384,7 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz
OrganizationResource organization = testRealm().organizations().get(createOrganization().getId()); OrganizationResource organization = testRealm().organizations().get(createOrganization().getId());
// add the member for the first time // add the member for the first time
assertBrokerRegistration(organization, bc.getUserEmail()); assertBrokerRegistration(organization, bc.getUserLogin(), bc.getUserEmail());
UserRepresentation member = getUserRepresentation(bc.getUserEmail()); UserRepresentation member = getUserRepresentation(bc.getUserEmail());
OrganizationMemberResource organizationMember = organization.members().member(member.getId()); OrganizationMemberResource organizationMember = organization.members().member(member.getId());
@ -635,7 +646,7 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz
public void testAllowUpdateEmailWithDifferentDomainThanOrgIfBrokerHasNoDomainSet() { public void testAllowUpdateEmailWithDifferentDomainThanOrgIfBrokerHasNoDomainSet() {
OrganizationResource organization = testRealm().organizations().get(createOrganization().getId()); OrganizationResource organization = testRealm().organizations().get(createOrganization().getId());
String email = bc.getUserEmail(); String email = bc.getUserEmail();
assertBrokerRegistration(organization, email); assertBrokerRegistration(organization, bc.getUserLogin(), email);
IdentityProviderRepresentation idpRep = organization.identityProviders().getIdentityProviders().get(0); IdentityProviderRepresentation idpRep = organization.identityProviders().getIdentityProviders().get(0);
idpRep.getConfig().remove(OrganizationModel.ORGANIZATION_DOMAIN_ATTRIBUTE); idpRep.getConfig().remove(OrganizationModel.ORGANIZATION_DOMAIN_ATTRIBUTE);
@ -649,7 +660,7 @@ public abstract class AbstractBrokerSelfRegistrationTest extends AbstractOrganiz
public void testFailUpdateEmailWithDifferentDomainThanOrgIfBrokerHasDomainSet() { public void testFailUpdateEmailWithDifferentDomainThanOrgIfBrokerHasDomainSet() {
OrganizationResource organization = testRealm().organizations().get(createOrganization().getId()); OrganizationResource organization = testRealm().organizations().get(createOrganization().getId());
String email = bc.getUserEmail(); String email = bc.getUserEmail();
assertBrokerRegistration(organization, email); assertBrokerRegistration(organization, bc.getUserLogin(), email);
IdentityProviderRepresentation idpRep = organization.identityProviders().getIdentityProviders().get(0); IdentityProviderRepresentation idpRep = organization.identityProviders().getIdentityProviders().get(0);
assertEquals(email.substring(email.indexOf('@') + 1), idpRep.getConfig().get(OrganizationModel.ORGANIZATION_DOMAIN_ATTRIBUTE)); assertEquals(email.substring(email.indexOf('@') + 1), idpRep.getConfig().get(OrganizationModel.ORGANIZATION_DOMAIN_ATTRIBUTE));
UserRepresentation user = getUserRepresentation(email); UserRepresentation user = getUserRepresentation(email);

View file

@ -187,7 +187,7 @@ public class OrganizationMemberTest extends AbstractOrganizationTest {
} }
// onboard a test user by authenticating using the organization's provider. // onboard a test user by authenticating using the organization's provider.
super.assertBrokerRegistration(organization, bc.getUserEmail()); super.assertBrokerRegistration(organization, bc.getUserLogin(), bc.getUserEmail());
// disable the organization and check that fetching its representation has it disabled. // disable the organization and check that fetching its representation has it disabled.
orgRep.setEnabled(false); orgRep.setEnabled(false);
@ -246,7 +246,7 @@ public class OrganizationMemberTest extends AbstractOrganizationTest {
} }
// onboard a test user by authenticating using the organization's provider. // onboard a test user by authenticating using the organization's provider.
super.assertBrokerRegistration(organization, bc.getUserEmail()); super.assertBrokerRegistration(organization, bc.getUserLogin(), bc.getUserEmail());
// now fetch all users from the realm // now fetch all users from the realm
List<UserRepresentation> members = testRealm().users().search("*neworg*", null, null); List<UserRepresentation> members = testRealm().users().search("*neworg*", null, null);