openid-connect flow is missing response type on language change

closes #41292

Signed-off-by: mposolda <mposolda@gmail.com>
This commit is contained in:
mposolda 2025-10-09 13:32:08 +02:00 committed by Marek Posolda
parent 17fb20c58d
commit 76d271bf00
3 changed files with 50 additions and 4 deletions

View File

@ -523,6 +523,9 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
case LOGOUT_CONFIRM:
b = UriBuilder.fromUri(Urls.logoutConfirm(baseUri, realm.getName()));
break;
case LOGIN_PAGE_EXPIRED:
b = UriBuilder.fromUri(baseUri).path(uriInfo.getPath());
break;
case INFO:
case ERROR:
if (isDetachedAuthenticationSession()) {
@ -540,12 +543,11 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
break;
}
default:
b = UriBuilder.fromUri(baseUri).path(uriInfo.getPath());
b = getDefaultPageUriForLocale(baseUri);
break;
}
} else {
b = UriBuilder.fromUri(baseUri)
.path(uriInfo.getPath());
b = getDefaultPageUriForLocale(baseUri);
}
if (execution != null) {
@ -591,6 +593,12 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
attributes.put("lang", lang);
}
private UriBuilder getDefaultPageUriForLocale(URI baseUri) {
// Using "actionUri" by default in the language combobox when available
return actionUri != null ? UriBuilder.fromUri(actionUri.getPath()).replaceQuery(baseUri.getQuery()) :
UriBuilder.fromUri(baseUri).path(uriInfo.getPath());
}
/**
* Process FreeMarker template and prepare Response. Some fields are used for rendering also.
*

View File

@ -23,7 +23,7 @@ import org.openqa.selenium.support.FindBy;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class TermsAndConditionsPage extends AbstractPage {
public class TermsAndConditionsPage extends LanguageComboboxAwarePage {
@FindBy(id = "kc-accept")
private WebElement submitButton;

View File

@ -34,11 +34,13 @@ import org.keycloak.events.Details;
import org.keycloak.events.EventType;
import org.keycloak.forms.login.freemarker.DetachedInfoStateChecker;
import org.keycloak.locale.LocaleSelectorProvider;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.testsuite.AssertEvents;
import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.testsuite.forms.ClickThroughAuthenticator;
import org.keycloak.testsuite.pages.AppPage;
import org.keycloak.testsuite.pages.ErrorPage;
import org.keycloak.testsuite.pages.LanguageComboboxAwarePage;
@ -47,7 +49,9 @@ import org.keycloak.testsuite.pages.LoginPage;
import org.keycloak.testsuite.pages.LoginPasswordUpdatePage;
import org.keycloak.testsuite.pages.OAuthGrantPage;
import org.keycloak.testsuite.pages.PageUtils;
import org.keycloak.testsuite.pages.TermsAndConditionsPage;
import org.keycloak.testsuite.updaters.UserAttributeUpdater;
import org.keycloak.testsuite.util.FlowUtil;
import org.keycloak.testsuite.util.IdentityProviderBuilder;
import org.keycloak.testsuite.util.UIUtils;
import org.openqa.selenium.Cookie;
@ -88,6 +92,9 @@ public class LoginPageTest extends AbstractI18NTest {
@Page
protected LoginExpiredPage loginExpiredPage;
@Page
protected TermsAndConditionsPage termsPage;
@Rule
public AssertEvents events = new AssertEvents(this);
@ -372,6 +379,23 @@ public class LoginPageTest extends AbstractI18NTest {
}
}
// GH issue 41292
@Test
public void languageUserUpdatesOnCustomAuthenticatorPage() {
configureBrowserFlowWithClickThroughAuthenticator();
loginPage.open();
Assert.assertTrue(termsPage.isCurrent());
// Change language on the custom page
switchLanguageToGermanAndBack("Terms and Conditions", "Bedingungen und Konditionen", termsPage);
// Revert dummy flow
RealmRepresentation rep = testRealm().toRepresentation();
rep.setBrowserFlow("browser");
testRealm().update(rep);
}
@Test
public void realmLocalizationMessagesAreApplied() {
String realmLocalizationMessageKey = "loginAccountTitle";
@ -445,4 +469,18 @@ public class LoginPageTest extends AbstractI18NTest {
realm.setInternationalizationEnabled(enabled);
realmResource.update(realm);
}
private void configureBrowserFlowWithClickThroughAuthenticator() {
final String newFlowAlias = "browser - rule";
testingClient.server("test").run(session -> FlowUtil.inCurrentRealm(session).copyBrowserFlow(newFlowAlias));
testingClient.server("test").run(session -> FlowUtil.inCurrentRealm(session)
.selectFlow(newFlowAlias)
.inForms(forms -> forms
.clear()
// Update the browser forms with a UsernamePasswordForm
.addAuthenticatorExecution(AuthenticationExecutionModel.Requirement.REQUIRED, ClickThroughAuthenticator.PROVIDER_ID)
)
.defineAsBrowserFlow()
);
}
}