keycloak-uncached

Details

diff --git a/services/src/main/java/org/keycloak/forms/login/freemarker/FreeMarkerLoginFormsProvider.java b/services/src/main/java/org/keycloak/forms/login/freemarker/FreeMarkerLoginFormsProvider.java
index 35743fa..8b92110 100755
--- a/services/src/main/java/org/keycloak/forms/login/freemarker/FreeMarkerLoginFormsProvider.java
+++ b/services/src/main/java/org/keycloak/forms/login/freemarker/FreeMarkerLoginFormsProvider.java
@@ -401,6 +401,10 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
                     b.queryParam(Constants.EXECUTION, execution);
                 }
 
+                if (authenticationSession != null && authenticationSession.getAuthNote(Constants.KEY) != null) {
+                    b.queryParam(Constants.KEY, authenticationSession.getAuthNote(Constants.KEY));
+                }
+
                 attributes.put("locale", new LocaleBean(realm, locale, b, messagesBundle));
             }
         }
diff --git a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
index f6be313..ccaadb5 100755
--- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
+++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java
@@ -206,7 +206,7 @@ public class LoginActionsService {
     @Path(RESTART_PATH)
     @GET
     public Response restartSession(@QueryParam(AUTH_SESSION_ID) String authSessionId, // optional, can get from cookie instead
-                                   @QueryParam("client_id") String clientId,
+                                   @QueryParam(Constants.CLIENT_ID) String clientId,
                                    @QueryParam(Constants.TAB_ID) String tabId) {
         event.event(EventType.RESTART_AUTHENTICATION);
         SessionCodeChecks checks = new SessionCodeChecks(realm, uriInfo, request, clientConnection, session, event, authSessionId, null, null, clientId,  tabId, null);
@@ -239,8 +239,8 @@ public class LoginActionsService {
     @GET
     public Response authenticate(@QueryParam(AUTH_SESSION_ID) String authSessionId, // optional, can get from cookie instead
                                  @QueryParam(SESSION_CODE) String code,
-                                 @QueryParam("execution") String execution,
-                                 @QueryParam("client_id") String clientId,
+                                 @QueryParam(Constants.EXECUTION) String execution,
+                                 @QueryParam(Constants.CLIENT_ID) String clientId,
                                  @QueryParam(Constants.TAB_ID) String tabId) {
         event.event(EventType.LOGIN);
 
@@ -310,8 +310,8 @@ public class LoginActionsService {
     @POST
     public Response authenticateForm(@QueryParam(AUTH_SESSION_ID) String authSessionId, // optional, can get from cookie instead
                                      @QueryParam(SESSION_CODE) String code,
-                                     @QueryParam("execution") String execution,
-                                     @QueryParam("client_id") String clientId,
+                                     @QueryParam(Constants.EXECUTION) String execution,
+                                     @QueryParam(Constants.CLIENT_ID) String clientId,
                                      @QueryParam(Constants.TAB_ID) String tabId) {
         return authenticate(authSessionId, code, execution, clientId, tabId);
     }
@@ -320,8 +320,8 @@ public class LoginActionsService {
     @POST
     public Response resetCredentialsPOST(@QueryParam(AUTH_SESSION_ID) String authSessionId, // optional, can get from cookie instead
                                          @QueryParam(SESSION_CODE) String code,
-                                         @QueryParam("execution") String execution,
-                                         @QueryParam("client_id") String clientId,
+                                         @QueryParam(Constants.EXECUTION) String execution,
+                                         @QueryParam(Constants.CLIENT_ID) String clientId,
                                          @QueryParam(Constants.TAB_ID) String tabId,
                                          @QueryParam(Constants.KEY) String key) {
         if (key != null) {
@@ -345,8 +345,8 @@ public class LoginActionsService {
     @GET
     public Response resetCredentialsGET(@QueryParam(AUTH_SESSION_ID) String authSessionId, // optional, can get from cookie instead
                                         @QueryParam(SESSION_CODE) String code,
-                                        @QueryParam("execution") String execution,
-                                        @QueryParam("client_id") String clientId,
+                                        @QueryParam(Constants.EXECUTION) String execution,
+                                        @QueryParam(Constants.CLIENT_ID) String clientId,
                                         @QueryParam(Constants.TAB_ID) String tabId) {
         ClientModel client = realm.getClientByClientId(clientId);
         AuthenticationSessionModel authSession = new AuthenticationSessionManager(session).getCurrentAuthenticationSession(realm, client, tabId);
@@ -421,9 +421,9 @@ public class LoginActionsService {
     @Path("action-token")
     @GET
     public Response executeActionToken(@QueryParam(AUTH_SESSION_ID) String authSessionId,
-                                       @QueryParam("key") String key,
-                                       @QueryParam("execution") String execution,
-                                       @QueryParam("client_id") String clientId,
+                                       @QueryParam(Constants.KEY) String key,
+                                       @QueryParam(Constants.EXECUTION) String execution,
+                                       @QueryParam(Constants.CLIENT_ID) String clientId,
                                        @QueryParam(Constants.TAB_ID) String tabId) {
         return handleActionToken(key, execution, clientId, tabId);
     }
@@ -557,6 +557,8 @@ public class LoginActionsService {
 
             authSession.setAuthNote(DefaultActionTokenKey.ACTION_TOKEN_USER_ID, token.getUserId());
 
+            authSession.setAuthNote(Constants.KEY, tokenString);
+
             return handler.handleToken(token, tokenContext);
         } catch (ExplainedTokenVerificationException ex) {
             return handleActionTokenVerificationException(tokenContext, ex, ex.getErrorEvent(), ex.getMessage());
@@ -627,8 +629,8 @@ public class LoginActionsService {
     @GET
     public Response registerPage(@QueryParam(AUTH_SESSION_ID) String authSessionId, // optional, can get from cookie instead
                                  @QueryParam(SESSION_CODE) String code,
-                                 @QueryParam("execution") String execution,
-                                 @QueryParam("client_id") String clientId,
+                                 @QueryParam(Constants.EXECUTION) String execution,
+                                 @QueryParam(Constants.CLIENT_ID) String clientId,
                                  @QueryParam(Constants.TAB_ID) String tabId) {
         return registerRequest(authSessionId, code, execution, clientId,  tabId,false);
     }
@@ -644,8 +646,8 @@ public class LoginActionsService {
     @POST
     public Response processRegister(@QueryParam(AUTH_SESSION_ID) String authSessionId, // optional, can get from cookie instead
                                     @QueryParam(SESSION_CODE) String code,
-                                    @QueryParam("execution") String execution,
-                                    @QueryParam("client_id") String clientId,
+                                    @QueryParam(Constants.EXECUTION) String execution,
+                                    @QueryParam(Constants.CLIENT_ID) String clientId,
                                     @QueryParam(Constants.TAB_ID) String tabId) {
         return registerRequest(authSessionId, code, execution, clientId,  tabId,true);
     }
@@ -675,8 +677,8 @@ public class LoginActionsService {
     @GET
     public Response firstBrokerLoginGet(@QueryParam(AUTH_SESSION_ID) String authSessionId, // optional, can get from cookie instead
                                         @QueryParam(SESSION_CODE) String code,
-                                        @QueryParam("execution") String execution,
-                                        @QueryParam("client_id") String clientId,
+                                        @QueryParam(Constants.EXECUTION) String execution,
+                                        @QueryParam(Constants.CLIENT_ID) String clientId,
                                         @QueryParam(Constants.TAB_ID) String tabId) {
         return brokerLoginFlow(authSessionId, code, execution, clientId, tabId, FIRST_BROKER_LOGIN_PATH);
     }
@@ -685,8 +687,8 @@ public class LoginActionsService {
     @POST
     public Response firstBrokerLoginPost(@QueryParam(AUTH_SESSION_ID) String authSessionId, // optional, can get from cookie instead
                                          @QueryParam(SESSION_CODE) String code,
-                                         @QueryParam("execution") String execution,
-                                         @QueryParam("client_id") String clientId,
+                                         @QueryParam(Constants.EXECUTION) String execution,
+                                         @QueryParam(Constants.CLIENT_ID) String clientId,
                                          @QueryParam(Constants.TAB_ID) String tabId) {
         return brokerLoginFlow(authSessionId, code, execution, clientId, tabId, FIRST_BROKER_LOGIN_PATH);
     }
@@ -695,8 +697,8 @@ public class LoginActionsService {
     @GET
     public Response postBrokerLoginGet(@QueryParam(AUTH_SESSION_ID) String authSessionId, // optional, can get from cookie instead
                                        @QueryParam(SESSION_CODE) String code,
-                                       @QueryParam("execution") String execution,
-                                       @QueryParam("client_id") String clientId,
+                                       @QueryParam(Constants.EXECUTION) String execution,
+                                       @QueryParam(Constants.CLIENT_ID) String clientId,
                                        @QueryParam(Constants.TAB_ID) String tabId) {
         return brokerLoginFlow(authSessionId, code, execution, clientId, tabId, POST_BROKER_LOGIN_PATH);
     }
@@ -705,8 +707,8 @@ public class LoginActionsService {
     @POST
     public Response postBrokerLoginPost(@QueryParam(AUTH_SESSION_ID) String authSessionId, // optional, can get from cookie instead
                                         @QueryParam(SESSION_CODE) String code,
-                                        @QueryParam("execution") String execution,
-                                        @QueryParam("client_id") String clientId,
+                                        @QueryParam(Constants.EXECUTION) String execution,
+                                        @QueryParam(Constants.CLIENT_ID) String clientId,
                                         @QueryParam(Constants.TAB_ID) String tabId) {
         return brokerLoginFlow(authSessionId, code, execution, clientId, tabId, POST_BROKER_LOGIN_PATH);
     }
@@ -892,8 +894,8 @@ public class LoginActionsService {
     @POST
     public Response requiredActionPOST(@QueryParam(AUTH_SESSION_ID) String authSessionId, // optional, can get from cookie instead
                                        @QueryParam(SESSION_CODE) final String code,
-                                       @QueryParam("execution") String action,
-                                       @QueryParam("client_id") String clientId,
+                                       @QueryParam(Constants.EXECUTION) String action,
+                                       @QueryParam(Constants.CLIENT_ID) String clientId,
                                        @QueryParam(Constants.TAB_ID) String tabId) {
         return processRequireAction(authSessionId, code, action, clientId, tabId);
     }
@@ -902,8 +904,8 @@ public class LoginActionsService {
     @GET
     public Response requiredActionGET(@QueryParam(AUTH_SESSION_ID) String authSessionId, // optional, can get from cookie instead
                                       @QueryParam(SESSION_CODE) final String code,
-                                      @QueryParam("execution") String action,
-                                      @QueryParam("client_id") String clientId,
+                                      @QueryParam(Constants.EXECUTION) String action,
+                                      @QueryParam(Constants.CLIENT_ID) String clientId,
                                       @QueryParam(Constants.TAB_ID) String tabId) {
         return processRequireAction(authSessionId, code, action, clientId, tabId);
     }
diff --git a/services/src/main/java/org/keycloak/services/Urls.java b/services/src/main/java/org/keycloak/services/Urls.java
index ac45614..49cb044 100755
--- a/services/src/main/java/org/keycloak/services/Urls.java
+++ b/services/src/main/java/org/keycloak/services/Urls.java
@@ -16,7 +16,6 @@
  */
 package org.keycloak.services;
 
-import org.keycloak.OAuth2Constants;
 import org.keycloak.common.Version;
 import org.keycloak.models.Constants;
 import org.keycloak.protocol.oidc.OIDCLoginProtocol;
@@ -190,7 +189,7 @@ public class Urls {
 
     public static UriBuilder actionTokenBuilder(URI baseUri, String tokenString, String clientId, String tabId) {
         return loginActionsBase(baseUri).path(LoginActionsService.class, "executeActionToken")
-                .queryParam("key", tokenString)
+                .queryParam(Constants.KEY, tokenString)
                 .queryParam(Constants.CLIENT_ID, clientId)
                 .queryParam(Constants.TAB_ID, tabId);
 
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/InfoPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/InfoPage.java
index 346a0db..562ad0d 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/InfoPage.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/InfoPage.java
@@ -18,6 +18,7 @@
 package org.keycloak.testsuite.pages;
 
 import org.jboss.arquillian.test.api.ArquillianResource;
+import org.keycloak.testsuite.util.DroneUtils;
 import org.keycloak.testsuite.util.OAuthClient;
 import org.openqa.selenium.WebElement;
 import org.openqa.selenium.support.FindBy;
@@ -25,7 +26,7 @@ import org.openqa.selenium.support.FindBy;
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
-public class InfoPage extends AbstractPage {
+public class InfoPage extends LanguageComboboxAwarePage {
 
     @ArquillianResource
     protected OAuthClient oauth;
@@ -36,12 +37,16 @@ public class InfoPage extends AbstractPage {
     @FindBy(linkText = "« Back to Application")
     private WebElement backToApplicationLink;
 
+    @FindBy(linkText = "» Klicken Sie hier um fortzufahren")
+    private WebElement clickToContinueDe;
+
     public String getInfo() {
         return infoMessage.getText();
     }
 
+    @Override
     public boolean isCurrent() {
-        return driver.getPageSource().contains("kc-info-message");
+        return DroneUtils.getCurrentDriver().getPageSource().contains("kc-info-message");
     }
 
     @Override
@@ -53,4 +58,8 @@ public class InfoPage extends AbstractPage {
         backToApplicationLink.click();
     }
 
+    public void clickToContinueDe() {
+        clickToContinueDe.click();
+    }
+
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LanguageComboboxAwarePage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LanguageComboboxAwarePage.java
index 29d512e..e1e75de 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LanguageComboboxAwarePage.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/pages/LanguageComboboxAwarePage.java
@@ -17,6 +17,7 @@
 
 package org.keycloak.testsuite.pages;
 
+import org.keycloak.testsuite.util.WaitUtils;
 import org.openqa.selenium.By;
 import org.openqa.selenium.WebElement;
 import org.openqa.selenium.support.FindBy;
@@ -40,5 +41,6 @@ public abstract class LanguageComboboxAwarePage extends AbstractPage {
         WebElement langLink = localeDropdown.findElement(By.xpath("//a[text()='" + language + "']"));
         String url = langLink.getAttribute("href");
         driver.navigate().to(url);
+        WaitUtils.waitForPageToLoad();
     }
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/DemoServletsAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/DemoServletsAdapterTest.java
index 3048cb9..74cfe95 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/DemoServletsAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/DemoServletsAdapterTest.java
@@ -668,6 +668,7 @@ public class DemoServletsAdapterTest extends AbstractServletsAdapterTest {
     public void testVersion() {
         jsDriver.navigate().to(suiteContext.getAuthServerInfo().getContextRoot().toString() +
                 "/auth/admin/master/console/#/server-info");
+        WaitUtils.waitForPageToLoad();
         jsDriverTestRealmLoginPage.form().login("admin", "admin");
 
         WaitUtils.waitUntilElement(By.tagName("body")).is().visible();
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/i18n/EmailTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/i18n/EmailTest.java
index b799833..1bfb4bd 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/i18n/EmailTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/i18n/EmailTest.java
@@ -16,23 +16,31 @@
  */
 package org.keycloak.testsuite.i18n;
 
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+import java.io.IOException;
+import java.util.Arrays;
 import org.jboss.arquillian.graphene.page.Page;
 import org.junit.Assert;
 import org.junit.Rule;
 import org.junit.Test;
+import org.keycloak.admin.client.resource.UserResource;
 import org.keycloak.models.UserModel;
 import org.keycloak.representations.idm.UserRepresentation;
+import org.keycloak.testsuite.ProfileAssume;
 import org.keycloak.testsuite.admin.ApiUtil;
+import org.keycloak.testsuite.pages.InfoPage;
 import org.keycloak.testsuite.pages.LoginPage;
 import org.keycloak.testsuite.pages.LoginPasswordResetPage;
+import org.keycloak.testsuite.pages.LoginPasswordUpdatePage;
+import org.keycloak.testsuite.util.DroneUtils;
 import org.keycloak.testsuite.util.GreenMailRule;
-
-import javax.mail.MessagingException;
-import javax.mail.internet.MimeMessage;
-import java.io.IOException;
-
-import static org.junit.Assert.assertEquals;
-import org.keycloak.testsuite.ProfileAssume;
+import org.keycloak.testsuite.util.MailUtils;
+import org.keycloak.testsuite.util.WaitUtils;
 
 /**
  * @author <a href="mailto:gerbermichi@me.com">Michael Gerber</a>
@@ -49,6 +57,12 @@ public class EmailTest extends AbstractI18NTest {
     @Page
     protected LoginPasswordResetPage resetPasswordPage;
 
+    @Page
+    private InfoPage infoPage;
+
+    @Page
+    private LoginPasswordUpdatePage loginPasswordUpdatePage;
+
     private void changeUserLocale(String locale) {
         UserRepresentation user = findUser("login-test");
         user.singleAttribute(UserModel.LOCALE, locale);
@@ -61,7 +75,7 @@ public class EmailTest extends AbstractI18NTest {
         loginPage.resetPassword();
         resetPasswordPage.changePassword("login-test");
 
-        assertEquals(1, greenMail.getReceivedMessages().length);
+        Assert.assertEquals(1, greenMail.getReceivedMessages().length);
 
         MimeMessage message = greenMail.getReceivedMessages()[0];
 
@@ -74,7 +88,7 @@ public class EmailTest extends AbstractI18NTest {
 
         resetPasswordPage.changePassword("login-test");
 
-        assertEquals(2, greenMail.getReceivedMessages().length);
+        Assert.assertEquals(2, greenMail.getReceivedMessages().length);
 
         message = greenMail.getReceivedMessages()[1];
 
@@ -91,7 +105,7 @@ public class EmailTest extends AbstractI18NTest {
         loginPage.resetPassword();
         resetPasswordPage.changePassword("login-test");
 
-        assertEquals(1, greenMail.getReceivedMessages().length);
+        Assert.assertEquals(1, greenMail.getReceivedMessages().length);
 
         MimeMessage message = greenMail.getReceivedMessages()[0];
 
@@ -101,4 +115,37 @@ public class EmailTest extends AbstractI18NTest {
         changeUserLocale("en");
     }
 
+    //KEYCLOAK-7478
+    @Test
+    public void changeLocaleOnInfoPage() throws InterruptedException, IOException, MessagingException {
+        ProfileAssume.assumeCommunity();
+              
+        UserResource testUser = ApiUtil.findUserByUsernameId(testRealm(), "login-test");
+        testUser.executeActionsEmail(Arrays.asList(UserModel.RequiredAction.UPDATE_PASSWORD.toString()));
+        
+        if (!greenMail.waitForIncomingEmail(1)) {
+            Assert.fail("Error when receiving email");
+        }
+        
+        String link = MailUtils.getPasswordResetEmailLink(greenMail.getLastReceivedMessage());
+        
+        DroneUtils.getCurrentDriver().navigate().to(link);
+        WaitUtils.waitForPageToLoad();
+        
+        Assert.assertTrue("Expected to be on InfoPage, but it was on " + DroneUtils.getCurrentDriver().getTitle(), infoPage.isCurrent());
+        Assert.assertThat(infoPage.getLanguageDropdownText(), is(equalTo("English")));
+        
+        infoPage.openLanguage("Deutsch");
+
+        Assert.assertThat(DroneUtils.getCurrentDriver().getPageSource(), containsString("Passwort aktualisieren"));
+        
+        infoPage.clickToContinueDe();
+        
+        loginPasswordUpdatePage.openLanguage("English");
+        loginPasswordUpdatePage.changePassword("pass", "pass");
+        WaitUtils.waitForPageToLoad();
+        
+        Assert.assertTrue("Expected to be on InfoPage, but it was on " + DroneUtils.getCurrentDriver().getTitle(), infoPage.isCurrent());
+        Assert.assertThat(infoPage.getInfo(), containsString("Your account has been updated."));
+    }
 }