keycloak-memoizeit

Merge pull request #215 from stianst/master KEYCLOAK-297

2/17/2014 12:15:13 PM

Details

diff --git a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccount.java b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccount.java
index 9c5a687..64f4135 100644
--- a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccount.java
+++ b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/FreeMarkerAccount.java
@@ -5,6 +5,7 @@ import org.keycloak.account.Account;
 import org.keycloak.account.AccountPages;
 import org.keycloak.account.freemarker.model.AccountBean;
 import org.keycloak.account.freemarker.model.MessageBean;
+import org.keycloak.account.freemarker.model.ReferrerBean;
 import org.keycloak.account.freemarker.model.TotpBean;
 import org.keycloak.account.freemarker.model.UrlBean;
 import org.keycloak.freemarker.FreeMarkerException;
@@ -80,7 +81,12 @@ public class FreeMarkerAccount implements Account {
             attributes.put("message", new MessageBean(messages.containsKey(message) ? messages.getProperty(message) : message, messageType));
         }
 
-        attributes.put("url", new UrlBean(realm, theme, baseUri, getReferrerUri()));
+        ApplicationModel referrerApp = getReferrer();
+        if (referrerApp != null) {
+            attributes.put("referrer", new ReferrerBean(referrerApp));
+        }
+
+        attributes.put("url", new UrlBean(realm, theme, baseUri));
 
         switch (page) {
             case ACCOUNT:
@@ -100,11 +106,11 @@ public class FreeMarkerAccount implements Account {
         }
     }
 
-    private String getReferrerUri() {
+    private ApplicationModel getReferrer() {
         if (referrer != null) {
             ApplicationModel app = realm.getApplicationByName(referrer);
             if (app != null) {
-                return app.getBaseUrl();
+                return app;
             }
         }
         return null;
diff --git a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/ReferrerBean.java b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/ReferrerBean.java
new file mode 100644
index 0000000..8904bf6
--- /dev/null
+++ b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/ReferrerBean.java
@@ -0,0 +1,24 @@
+package org.keycloak.account.freemarker.model;
+
+import org.keycloak.models.ApplicationModel;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class ReferrerBean {
+
+    private ApplicationModel referrer;
+
+    public ReferrerBean(ApplicationModel referrer) {
+        this.referrer = referrer;
+    }
+
+    public String getName() {
+        return referrer.getName();
+    }
+
+    public String getBaseUrl() {
+        return referrer.getBaseUrl();
+    }
+
+}
diff --git a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/UrlBean.java b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/UrlBean.java
index 46dbb4e..53dde7c 100644
--- a/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/UrlBean.java
+++ b/forms/account-freemarker/src/main/java/org/keycloak/account/freemarker/model/UrlBean.java
@@ -14,13 +14,11 @@ public class UrlBean {
     private String realm;
     private Theme theme;
     private URI baseURI;
-    private String referrerURI;
 
-    public UrlBean(RealmModel realm, Theme theme, URI baseURI, String referrerURI) {
+    public UrlBean(RealmModel realm, Theme theme, URI baseURI) {
         this.realm = realm.getName();
         this.theme = theme;
         this.baseURI = baseURI;
-        this.referrerURI = referrerURI;
     }
 
     public String getAccessUrl() {
@@ -51,10 +49,6 @@ public class UrlBean {
         return Urls.accountLogout(baseURI, realm).toString();
     }
 
-    public String getReferrerURI() {
-        return referrerURI;
-    }
-
     public String getResourcesPath() {
         URI uri = Urls.themeRoot(baseURI);
         return uri.getPath() + "/" + theme.getType().toString().toLowerCase() +"/" + theme.getName();
diff --git a/forms/common-themes/src/main/resources/theme/account/base/template.ftl b/forms/common-themes/src/main/resources/theme/account/base/template.ftl
index 66da0f8..355b583 100644
--- a/forms/common-themes/src/main/resources/theme/account/base/template.ftl
+++ b/forms/common-themes/src/main/resources/theme/account/base/template.ftl
@@ -29,7 +29,7 @@
 
                     <div class="navbar-collapse">
                         <ul class="nav navbar-nav navbar-utility">
-                            <#if url.referrerURI??><li><a href="${url.referrerURI}">Back to application</a></li></#if>
+                            <#if referrer?has_content><li><a href="${referrer.baseUrl}">Back to ${referrer.name}</a></li></#if>
                             <li><a href="${url.logoutUrl}">Sign Out</a></li>
                         </ul>
                     </div>
diff --git a/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsOAuthClient.java b/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsOAuthClient.java
index 89ee9bc..a090da7 100755
--- a/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsOAuthClient.java
+++ b/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsOAuthClient.java
@@ -82,14 +82,7 @@ public class JaxrsOAuthClient extends AbstractOAuthClient {
         }
     }
     public Response redirect(UriInfo uriInfo, String redirectUri) {
-        return redirect(uriInfo, redirectUri, null);
-    }
-
-    public Response redirect(UriInfo uriInfo, String redirectUri, String path) {
         String state = getStateCode();
-        if (path != null) {
-            state += "#" + path;
-        }
 
         UriBuilder uriBuilder = UriBuilder.fromUri(authUrl)
                 .queryParam("client_id", clientId)
@@ -98,6 +91,7 @@ public class JaxrsOAuthClient extends AbstractOAuthClient {
         if (scope != null) {
             uriBuilder.queryParam("scope", scope);
         }
+
         URI url = uriBuilder.build();
 
         NewCookie cookie = new NewCookie(getStateCookieName(), state, getStateCookiePath(uriInfo), null, null, -1, isSecure, true);
@@ -130,7 +124,7 @@ public class JaxrsOAuthClient extends AbstractOAuthClient {
         return uriInfo.getQueryParameters().getFirst("code");
     }
 
-    public String checkStateCookie(UriInfo uriInfo, HttpHeaders headers) {
+    public void checkStateCookie(UriInfo uriInfo, HttpHeaders headers) {
         Cookie stateCookie = headers.getCookies().get(stateCookieName);
         if (stateCookie == null) throw new BadRequestException("state cookie not set");
         String state = uriInfo.getQueryParameters().getFirst("state");
@@ -138,10 +132,5 @@ public class JaxrsOAuthClient extends AbstractOAuthClient {
         if (!state.equals(stateCookie.getValue())) {
             throw new BadRequestException("state parameter invalid");
         }
-        if (state.indexOf('#') != -1) {
-            return state.substring(state.indexOf('#') + 1);
-        } else {
-            return null;
-        }
     }
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java
index e63262a..7ceddc9 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -259,6 +259,8 @@ public class AccountService {
     public Response loginRedirect(@QueryParam("code") String code,
                                   @QueryParam("state") String state,
                                   @QueryParam("error") String error,
+                                  @QueryParam("path") String path,
+                                  @QueryParam("referrer") String referrer,
                                   @Context HttpHeaders headers) {
         try {
             if (error != null) {
@@ -282,7 +284,6 @@ public class AccountService {
                 logger.debug("state not specified");
                 throw new BadRequestException();
             }
-            String path = new JaxrsOAuthClient().checkStateCookie(uriInfo, headers);
 
             JWSInput input = new JWSInput(code);
             boolean verifiedCode = false;
@@ -321,6 +322,9 @@ public class AccountService {
 
             URI accountUri = Urls.accountBase(uriInfo.getBaseUri()).path("/").build(realm.getName());
             URI redirectUri = path != null ? accountUri.resolve(path) : accountUri;
+            if (referrer != null) {
+                redirectUri = redirectUri.resolve("?referrer=" + referrer);
+            }
 
             NewCookie cookie = authManager.createAccountIdentityCookie(realm, accessCode.getUser(), client, Urls.accountBase(uriInfo.getBaseUri()).build(realm.getName()));
             return Response.status(302).cookie(cookie).location(redirectUri).build();
@@ -346,15 +350,22 @@ public class AccountService {
 
         oauth.setClientId(Constants.ACCOUNT_APPLICATION);
 
-        URI accountUri = Urls.accountPageBuilder(uriInfo.getBaseUri()).path(AccountService.class, "loginRedirect").build(realm.getName());
+        UriBuilder uriBuilder = Urls.accountPageBuilder(uriInfo.getBaseUri()).path(AccountService.class, "loginRedirect");
+
+        if (path != null) {
+            uriBuilder.queryParam("path", path);
+        }
 
         String referrer = getReferrer();
         if (referrer != null) {
-            path = (path != null ? path : "") + "?referrer=" + referrer;
+            uriBuilder.queryParam("referrer", referrer);
         }
 
+        URI accountUri = uriBuilder.build(realm.getName());
+
+
         oauth.setStateCookiePath(accountUri.getRawPath());
-        return oauth.redirect(uriInfo, accountUri.toString(), path);
+        return oauth.redirect(uriInfo, accountUri.toString());
     }
 
     private AuthenticationManager.Auth getAuth(boolean error) {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java
index 0ae7163..8665803 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java
@@ -235,10 +235,15 @@ public class AdminService {
         logger.debug("authUrl: {0}", authUrl);
         oauth.setAuthUrl(authUrl);
         oauth.setClientId(Constants.ADMIN_CONSOLE_APPLICATION);
-        URI redirectUri = uriInfo.getBaseUriBuilder().path(AdminService.class).path(AdminService.class, "loginRedirect").build();
+
+        UriBuilder redirectBuilder = uriInfo.getBaseUriBuilder().path(AdminService.class).path(AdminService.class, "loginRedirect");
+        if (path != null) {
+            redirectBuilder.queryParam("path", path);
+        }
+        URI redirectUri = redirectBuilder.build();
         logger.debug("redirectUri: {0}", redirectUri.toString());
         oauth.setStateCookiePath(redirectUri.getRawPath());
-        return oauth.redirect(uriInfo, redirectUri.toString(), path);
+        return oauth.redirect(uriInfo, redirectUri.toString());
     }
 
     @Path("login-error")
@@ -263,6 +268,7 @@ public class AdminService {
     public Response loginRedirect(@QueryParam("code") String code,
                                   @QueryParam("state") String state,
                                   @QueryParam("error") String error,
+                                  @QueryParam("path") String path,
                                   @Context HttpHeaders headers
 
                                   ) {
@@ -293,7 +299,7 @@ public class AdminService {
                 logger.debug("state not specified");
                 return redirectOnLoginError("invalid login data");
             }
-            String path = new JaxrsOAuthClient().checkStateCookie(uriInfo, headers);
+            new JaxrsOAuthClient().checkStateCookie(uriInfo, headers);
 
             JWSInput input = new JWSInput(code);
             boolean verifiedCode = false;
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/SSOTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/SSOTest.java
new file mode 100644
index 0000000..15fc2ba
--- /dev/null
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/SSOTest.java
@@ -0,0 +1,84 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.keycloak.testsuite.forms;
+
+import org.junit.Assert;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.keycloak.testsuite.OAuthClient;
+import org.keycloak.testsuite.pages.AccountUpdateProfilePage;
+import org.keycloak.testsuite.pages.AppPage;
+import org.keycloak.testsuite.pages.AppPage.RequestType;
+import org.keycloak.testsuite.pages.LoginPage;
+import org.keycloak.testsuite.rule.KeycloakRule;
+import org.keycloak.testsuite.rule.WebResource;
+import org.keycloak.testsuite.rule.WebRule;
+import org.openqa.selenium.WebDriver;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class SSOTest {
+
+    @ClassRule
+    public static KeycloakRule keycloakRule = new KeycloakRule();
+
+    @Rule
+    public WebRule webRule = new WebRule(this);
+
+    @WebResource
+    protected OAuthClient oauth;
+
+
+    @WebResource
+    protected WebDriver driver;
+
+    @WebResource
+    protected AppPage appPage;
+
+    @WebResource
+    protected LoginPage loginPage;
+
+    @WebResource
+    protected AccountUpdateProfilePage profilePage;
+
+    @Test
+    public void loginSuccess() {
+        loginPage.open();
+        loginPage.login("test-user@localhost", "password");
+        
+        Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
+        Assert.assertNotNull(oauth.getCurrentQuery().get("code"));
+
+        appPage.open();
+
+        oauth.openLoginForm();
+
+        Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
+
+        profilePage.open();
+
+        Assert.assertTrue(profilePage.isCurrent());
+    }
+
+}