Flow steps back when changing locale or refreshing page on 'Try another way page'
closes #30520 Signed-off-by: mposolda <mposolda@gmail.com>
This commit is contained in:
parent
592c2250fc
commit
6a9e60bba0
3 changed files with 62 additions and 7 deletions
|
@ -90,6 +90,9 @@ public class AuthenticationProcessor {
|
||||||
public static final String BROKER_USER_ID = "broker.user.id";
|
public static final String BROKER_USER_ID = "broker.user.id";
|
||||||
public static final String FORWARDED_PASSIVE_LOGIN = "forwarded.passive.login";
|
public static final String FORWARDED_PASSIVE_LOGIN = "forwarded.passive.login";
|
||||||
|
|
||||||
|
// Boolean flag, which is true when authentication-selector screen should be rendered (typically displayed when user clicked on 'try another way' link)
|
||||||
|
public static final String AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED = "auth.selector.screen.rendered";
|
||||||
|
|
||||||
protected static final Logger logger = Logger.getLogger(AuthenticationProcessor.class);
|
protected static final Logger logger = Logger.getLogger(AuthenticationProcessor.class);
|
||||||
protected RealmModel realm;
|
protected RealmModel realm;
|
||||||
protected UserSessionModel userSession;
|
protected UserSessionModel userSession;
|
||||||
|
|
|
@ -93,16 +93,14 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
|
||||||
if (inputData.containsKey("tryAnotherWay")) {
|
if (inputData.containsKey("tryAnotherWay")) {
|
||||||
logger.trace("User clicked on link 'Try Another Way'");
|
logger.trace("User clicked on link 'Try Another Way'");
|
||||||
|
|
||||||
List<AuthenticationSelectionOption> selectionOptions = createAuthenticationSelectionList(model);
|
processor.getAuthenticationSession().setAuthNote(AuthenticationProcessor.AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED, "true");
|
||||||
|
return createSelectAuthenticatorsScreen(model);
|
||||||
AuthenticationProcessor.Result result = processor.createAuthenticatorContext(model, null, null);
|
|
||||||
result.setAuthenticationSelections(selectionOptions);
|
|
||||||
return result.form().createSelectAuthenticator();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the user has switched to a new authentication execution, and if so switch to it.
|
// check if the user has switched to a new authentication execution, and if so switch to it.
|
||||||
if (authExecId != null && !authExecId.isEmpty()) {
|
if (authExecId != null && !authExecId.isEmpty()) {
|
||||||
|
|
||||||
|
processor.getAuthenticationSession().removeAuthNote(AuthenticationProcessor.AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED);
|
||||||
List<AuthenticationSelectionOption> selectionOptions = createAuthenticationSelectionList(model);
|
List<AuthenticationSelectionOption> selectionOptions = createAuthenticationSelectionList(model);
|
||||||
|
|
||||||
// Check if switch to the requested authentication execution is allowed
|
// Check if switch to the requested authentication execution is allowed
|
||||||
|
@ -222,10 +220,35 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create screen where user can select from multiple authentication methods (Usually displayed when user clicks on 'try another way' link during authentication)
|
||||||
|
*
|
||||||
|
* @param executionModel Last execution (should be typically available in the methods)
|
||||||
|
* @return response with the screen to be displayed to the user
|
||||||
|
*/
|
||||||
|
private Response createSelectAuthenticatorsScreen(AuthenticationExecutionModel executionModel) {
|
||||||
|
List<AuthenticationSelectionOption> selectionOptions = createAuthenticationSelectionList(executionModel);
|
||||||
|
|
||||||
|
AuthenticationProcessor.Result result = processor.createAuthenticatorContext(executionModel, null, null);
|
||||||
|
result.setAuthenticationSelections(selectionOptions);
|
||||||
|
return result.form().createSelectAuthenticator();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response processFlow() {
|
public Response processFlow() {
|
||||||
logger.debugf("processFlow: %s", flow.getAlias());
|
logger.debugf("processFlow: %s", flow.getAlias());
|
||||||
|
|
||||||
|
if (Boolean.parseBoolean(processor.getAuthenticationSession().getAuthNote(AuthenticationProcessor.AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED))) {
|
||||||
|
logger.tracef("Refreshed page on authentication selector screen");
|
||||||
|
String lastExecutionId = processor.getAuthenticationSession().getAuthNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION);
|
||||||
|
if (lastExecutionId != null) {
|
||||||
|
AuthenticationExecutionModel executionModel = processor.getRealm().getAuthenticationExecutionById(lastExecutionId);
|
||||||
|
if (executionModel != null) {
|
||||||
|
return createSelectAuthenticatorsScreen(executionModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//separate flow elements into required and alternative elements
|
//separate flow elements into required and alternative elements
|
||||||
List<AuthenticationExecutionModel> requiredList = new ArrayList<>();
|
List<AuthenticationExecutionModel> requiredList = new ArrayList<>();
|
||||||
List<AuthenticationExecutionModel> alternativeList = new ArrayList<>();
|
List<AuthenticationExecutionModel> alternativeList = new ArrayList<>();
|
||||||
|
|
|
@ -159,6 +159,35 @@ public class MultiFactorAuthenticationTest extends AbstractTestRealmKeycloakTest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue https://github.com/keycloak/keycloak/issues/30520
|
||||||
|
@Test
|
||||||
|
public void testChangingLocaleOnAuthenticationSelectorScreen() {
|
||||||
|
try {
|
||||||
|
configureBrowserFlowWithAlternativeCredentials();
|
||||||
|
|
||||||
|
loginUsernameOnlyPage.open();
|
||||||
|
loginUsernameOnlyPage.login("user-with-one-configured-otp");
|
||||||
|
passwordPage.assertCurrent();
|
||||||
|
passwordPage.assertTryAnotherWayLinkAvailability(true);
|
||||||
|
passwordPage.clickTryAnotherWayLink();
|
||||||
|
|
||||||
|
selectAuthenticatorPage.assertCurrent();
|
||||||
|
Assert.assertEquals(Arrays.asList(SelectAuthenticatorPage.PASSWORD, SelectAuthenticatorPage.AUTHENTICATOR_APPLICATION), selectAuthenticatorPage.getAvailableLoginMethods());
|
||||||
|
|
||||||
|
// Switch locale. Should be still on "selectAuthenticatorPage"
|
||||||
|
selectAuthenticatorPage.openLanguage("Deutsch");
|
||||||
|
selectAuthenticatorPage.assertCurrent();
|
||||||
|
Assert.assertEquals(Arrays.asList("Passwort", "Authenticator-Anwendung"), selectAuthenticatorPage.getAvailableLoginMethods());
|
||||||
|
|
||||||
|
// Change language back
|
||||||
|
selectAuthenticatorPage.openLanguage("English");
|
||||||
|
selectAuthenticatorPage.assertCurrent();
|
||||||
|
Assert.assertEquals(Arrays.asList(SelectAuthenticatorPage.PASSWORD, SelectAuthenticatorPage.AUTHENTICATOR_APPLICATION), selectAuthenticatorPage.getAvailableLoginMethods());
|
||||||
|
} finally {
|
||||||
|
BrowserFlowTest.revertFlows(testRealm(), "browser - alternative");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void configureBrowserFlowWithAlternativeCredentials() {
|
private void configureBrowserFlowWithAlternativeCredentials() {
|
||||||
configureBrowserFlowWithAlternativeCredentials(testingClient);
|
configureBrowserFlowWithAlternativeCredentials(testingClient);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue