From c34415da4f0cd5af635e87fd06394dff00db4468 Mon Sep 17 00:00:00 2001 From: Sven-Torben Janus Date: Tue, 17 Dec 2024 20:09:24 +0100 Subject: [PATCH] fix: Ask for username on reauthentication when no session present When a client or federating IdP forces login (or reauthentication), but no user exists in the current session or no session is present at all, ask for the username on the login page. Fixes #475 Signed-off-by: Sven-Torben Janus --- .../hidpd/AuthenticationChallenge.java | 8 ++----- .../authentication/HomeIdpDiscoveryIT.java | 23 +++++++++++++++++++ .../authentication/pages/UpstreamIdpMock.java | 6 +++++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/main/java/de/sventorben/keycloak/authentication/hidpd/AuthenticationChallenge.java b/src/main/java/de/sventorben/keycloak/authentication/hidpd/AuthenticationChallenge.java index 6a2bd20..03ef032 100755 --- a/src/main/java/de/sventorben/keycloak/authentication/hidpd/AuthenticationChallenge.java +++ b/src/main/java/de/sventorben/keycloak/authentication/hidpd/AuthenticationChallenge.java @@ -32,11 +32,13 @@ void forceChallenge() { String rememberMeUsername = rememberMe.getUserName(); + Response challengeResponse; if (reauthentication.required() && context.getUser() != null) { String attribute = Optional.ofNullable(context.getAuthenticatorConfig()) .map(it -> it.getConfig().getOrDefault("userAttribute", "email").trim()) .orElse("email"); formData.add(AuthenticationManager.FORM_USERNAME, context.getUser().getFirstAttribute(attribute)); + challengeResponse = loginForm.createWithSignInButtonOnly(formData); } else { if (loginHintUsername != null || rememberMeUsername != null) { if (loginHintUsername != null) { @@ -46,12 +48,6 @@ void forceChallenge() { formData.add("rememberMe", "on"); } } - } - - Response challengeResponse; - if (reauthentication.required()) { - challengeResponse = loginForm.createWithSignInButtonOnly(formData); - } else { challengeResponse = loginForm.create(formData); } diff --git a/src/test/java/de/sventorben/keycloak/authentication/HomeIdpDiscoveryIT.java b/src/test/java/de/sventorben/keycloak/authentication/HomeIdpDiscoveryIT.java index f05077d..ae9fd8d 100755 --- a/src/test/java/de/sventorben/keycloak/authentication/HomeIdpDiscoveryIT.java +++ b/src/test/java/de/sventorben/keycloak/authentication/HomeIdpDiscoveryIT.java @@ -433,6 +433,29 @@ public void willForwardLoginHint() { } } + @Nested + @DisplayName("GH-475: Given no session and prompt=login") + class GivenNoSessionAndPromptLogin { + + @BeforeEach + public void setUp() { + upstreamIdpMock().redirectToDownstreamWithPromptLogin("test"); + } + + @Test + @DisplayName("then show username form field") + public void thenShowUsernameFormField() { + testRealmLoginPage().assertUsernameFieldIsDisplayed(); + } + + @Test + @DisplayName("then username form field is empty") + public void thenUsernameFormFieldIsEmpty() { + testRealmLoginPage().assertUsernameFieldIsPrefilledWith(""); + } + + } + @Nested @DisplayName("Given user is linked to an IdP already") class GivenUserHasIdpLinkConfigured { diff --git a/src/test/java/de/sventorben/keycloak/authentication/pages/UpstreamIdpMock.java b/src/test/java/de/sventorben/keycloak/authentication/pages/UpstreamIdpMock.java index 23bd282..07902cd 100755 --- a/src/test/java/de/sventorben/keycloak/authentication/pages/UpstreamIdpMock.java +++ b/src/test/java/de/sventorben/keycloak/authentication/pages/UpstreamIdpMock.java @@ -22,4 +22,10 @@ public void redirectToDownstreamWithLoginHint(String clientId, String loginHint) webDriver.navigate().to(keycloakBaseUrl + url); } + public void redirectToDownstreamWithPromptLogin(String clientId) { + String url = "/realms/test-realm/protocol/openid-connect/auth?client_id=" + clientId + "&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Frealms%2Ftest-realm%2Faccount%2F&response_mode=fragment&response_type=code&scope=openid"; + url += "&prompt=login"; + webDriver.navigate().to(keycloakBaseUrl + url); + } + }