Automatically fill username when authenticating to through a broker
Closes #28848 Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com>
This commit is contained in:
parent
1e3837421e
commit
f0f8a88489
5 changed files with 68 additions and 11 deletions
|
@ -75,6 +75,10 @@ public class IdentityProviderAuthenticator implements Authenticator {
|
|||
}
|
||||
|
||||
protected void redirect(AuthenticationFlowContext context, String providerId) {
|
||||
redirect(context, providerId, null);
|
||||
}
|
||||
|
||||
protected void redirect(AuthenticationFlowContext context, String providerId, String loginHint) {
|
||||
Optional<IdentityProviderModel> idp = context.getRealm().getIdentityProvidersStream()
|
||||
.filter(IdentityProviderModel::isEnabled)
|
||||
.filter(identityProvider -> Objects.equals(providerId, identityProvider.getAlias()))
|
||||
|
@ -84,7 +88,7 @@ public class IdentityProviderAuthenticator implements Authenticator {
|
|||
String clientId = context.getAuthenticationSession().getClient().getClientId();
|
||||
String tabId = context.getAuthenticationSession().getTabId();
|
||||
String clientData = AuthenticationProcessor.getClientData(context.getSession(), context.getAuthenticationSession());
|
||||
URI location = Urls.identityProviderAuthnRequest(context.getUriInfo().getBaseUri(), providerId, context.getRealm().getName(), accessCode, clientId, tabId, clientData);
|
||||
URI location = Urls.identityProviderAuthnRequest(context.getUriInfo().getBaseUri(), providerId, context.getRealm().getName(), accessCode, clientId, tabId, clientData, loginHint);
|
||||
Response response = Response.seeOther(location)
|
||||
.build();
|
||||
// will forward the request to the IDP with prompt=none if the IDP accepts forwards with prompt=none.
|
||||
|
|
|
@ -59,6 +59,12 @@ public class OrganizationAuthenticator extends IdentityProviderAuthenticator {
|
|||
}
|
||||
|
||||
String domain = getEmailDomain(username);
|
||||
|
||||
if (domain == null) {
|
||||
context.attempted();
|
||||
return;
|
||||
}
|
||||
|
||||
OrganizationProvider provider = getOrganizationProvider();
|
||||
OrganizationModel organization = provider.getByDomainName(domain);
|
||||
|
||||
|
@ -74,7 +80,7 @@ public class OrganizationAuthenticator extends IdentityProviderAuthenticator {
|
|||
return;
|
||||
}
|
||||
|
||||
redirect(context, identityProvider.getAlias());
|
||||
redirect(context, identityProvider.getAlias(), username);
|
||||
}
|
||||
|
||||
private OrganizationProvider getOrganizationProvider() {
|
||||
|
|
|
@ -52,7 +52,7 @@ public class Urls {
|
|||
.build(realmName, providerAlias);
|
||||
}
|
||||
|
||||
public static URI identityProviderAuthnRequest(URI baseUri, String providerAlias, String realmName, String accessCode, String clientId, String tabId, String clientData) {
|
||||
public static URI identityProviderAuthnRequest(URI baseUri, String providerAlias, String realmName, String accessCode, String clientId, String tabId, String clientData, String loginHint) {
|
||||
UriBuilder uriBuilder = realmBase(baseUri).path(RealmsResource.class, "getBrokerService")
|
||||
.path(IdentityBrokerService.class, "performLogin");
|
||||
|
||||
|
@ -68,6 +68,9 @@ public class Urls {
|
|||
if (clientData != null) {
|
||||
uriBuilder.replaceQueryParam(Constants.CLIENT_DATA, clientData);
|
||||
}
|
||||
if (loginHint != null) {
|
||||
uriBuilder.replaceQueryParam(OIDCLoginProtocol.LOGIN_HINT_PARAM, loginHint);
|
||||
}
|
||||
|
||||
return uriBuilder.build(realmName, providerAlias);
|
||||
}
|
||||
|
@ -87,7 +90,7 @@ public class Urls {
|
|||
}
|
||||
|
||||
public static URI identityProviderAuthnRequest(URI baseURI, String providerAlias, String realmName) {
|
||||
return identityProviderAuthnRequest(baseURI, providerAlias, realmName, null, null, null, null);
|
||||
return identityProviderAuthnRequest(baseURI, providerAlias, realmName, null, null, null, null, null);
|
||||
}
|
||||
|
||||
public static URI identityProviderAfterFirstBrokerLogin(URI baseUri, String realmName, String accessCode, String clientId, String tabId, String clientData) {
|
||||
|
|
|
@ -26,6 +26,8 @@ import org.junit.Test;
|
|||
import org.keycloak.admin.client.resource.OrganizationResource;
|
||||
import org.keycloak.admin.client.resource.UsersResource;
|
||||
import org.keycloak.common.Profile.Feature;
|
||||
import org.keycloak.models.IdentityProviderModel;
|
||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.testsuite.Assert;
|
||||
import org.keycloak.testsuite.arquillian.annotation.EnableFeature;
|
||||
|
@ -56,6 +58,29 @@ public class OrganizationBrokerSelfRegistrationTest extends AbstractOrganization
|
|||
assertBrokerRegistration(organization);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoginHint() {
|
||||
OrganizationResource organization = testRealm().organizations().get(createOrganization().getId());
|
||||
IdentityProviderRepresentation idp = organization.identityProvider().toRepresentation();
|
||||
idp.getConfig().put(IdentityProviderModel.LOGIN_HINT, "true");
|
||||
organization.identityProvider().update(idp).close();
|
||||
|
||||
oauth.clientId("broker-app");
|
||||
loginPage.open(bc.consumerRealmName());
|
||||
log.debug("Logging in");
|
||||
Assert.assertFalse(loginPage.isPasswordInputPresent());
|
||||
Assert.assertFalse(loginPage.isSocialButtonPresent(bc.getIDPAlias()));
|
||||
loginPage.loginUsername(bc.getUserEmail());
|
||||
|
||||
// user automatically redirected to the organization identity provider
|
||||
waitForPage(driver, "sign in to", true);
|
||||
Assert.assertTrue("Driver should be on the provider realm page right now",
|
||||
driver.getCurrentUrl().contains("/auth/realms/" + bc.providerRealmName() + "/"));
|
||||
// check if the username is automatically filled
|
||||
Assert.assertEquals(bc.getUserEmail(), loginPage.getUsername());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDefaultAuthenticationMechanismIfNotOrganizationMember() {
|
||||
testRealm().organizations().get(createOrganization().getId());
|
||||
|
@ -72,6 +97,22 @@ public class OrganizationBrokerSelfRegistrationTest extends AbstractOrganization
|
|||
Assert.assertTrue(loginPage.isPasswordInputPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTryLoginWithUsernameNotAnEmail() {
|
||||
testRealm().organizations().get(createOrganization().getId());
|
||||
oauth.clientId("broker-app");
|
||||
|
||||
// login with email only
|
||||
loginPage.open(bc.consumerRealmName());
|
||||
log.debug("Logging in");
|
||||
Assert.assertFalse(loginPage.isPasswordInputPresent());
|
||||
loginPage.loginUsername("user");
|
||||
|
||||
// check if the login page is shown
|
||||
Assert.assertTrue(loginPage.isUsernameInputPresent());
|
||||
Assert.assertTrue(loginPage.isPasswordInputPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLinkExistingAccount() {
|
||||
// create a realm user in the consumer realm
|
||||
|
@ -154,7 +195,6 @@ public class OrganizationBrokerSelfRegistrationTest extends AbstractOrganization
|
|||
waitForPage(driver, "sign in to", true);
|
||||
Assert.assertTrue("Driver should be on the provider realm page right now",
|
||||
driver.getCurrentUrl().contains("/auth/realms/" + bc.providerRealmName() + "/"));
|
||||
|
||||
// login to the organization identity provider and run the configured first broker login flow
|
||||
loginPage.login(bc.getUserEmail(), bc.getUserPassword());
|
||||
waitForPage(driver, "update account information", false);
|
||||
|
|
|
@ -23,6 +23,7 @@ import static org.hamcrest.Matchers.nullValue;
|
|||
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.Response.Status;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.OrganizationIdentityProviderResource;
|
||||
import org.keycloak.admin.client.resource.OrganizationResource;
|
||||
|
@ -38,16 +39,19 @@ public class OrganizationIdentityProviderTest extends AbstractOrganizationTest {
|
|||
public void testUpdate() {
|
||||
OrganizationRepresentation organization = createOrganization();
|
||||
OrganizationIdentityProviderResource orgIdPResource = testRealm().organizations().get(organization.getId()).identityProvider();
|
||||
IdentityProviderRepresentation idpRepresentation = orgIdPResource.toRepresentation();
|
||||
assertThat(idpRepresentation.getAlias(), equalTo(bc.getIDPAlias()));
|
||||
IdentityProviderRepresentation actual = orgIdPResource.toRepresentation();
|
||||
IdentityProviderRepresentation expected = actual;
|
||||
assertThat(expected.getAlias(), equalTo(bc.getIDPAlias()));
|
||||
|
||||
String displayName = "My Org Broker";
|
||||
//update
|
||||
idpRepresentation.setDisplayName(displayName);
|
||||
try (Response response = orgIdPResource.update(idpRepresentation)) {
|
||||
expected.setDisplayName("My Org Broker");
|
||||
expected.getConfig().put("test", "value");
|
||||
try (Response response = orgIdPResource.update(expected)) {
|
||||
assertThat(response.getStatus(), equalTo(Response.Status.NO_CONTENT.getStatusCode()));
|
||||
}
|
||||
assertThat(orgIdPResource.toRepresentation().getDisplayName(), equalTo(displayName));
|
||||
actual = orgIdPResource.toRepresentation();
|
||||
assertThat(expected.getDisplayName(), equalTo(actual.getDisplayName()));
|
||||
Assert.assertEquals(expected.getConfig().get("test"), actual.getConfig().get("test"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in a new issue