keycloak-memoizeit

fix menu error

8/18/2014 7:06:23 PM

Details

diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/realm-menu.html b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/realm-menu.html
index f527953..f34df5f 100755
--- a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/realm-menu.html
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/realm-menu.html
@@ -9,7 +9,7 @@
     </li>
     <li data-ng-show="access.viewUsers" data-ng-class="(path[2] == 'users' || path[1] == 'user') && 'active'"><a href="#/realms/{{realm.realm}}/users">Users</a>
     </li>
-    <li data-ng-show="access.viewRealm" data-ng-class="(path[2] == 'roles' || (path[1] == 'role' & path[3] != 'applications') && 'active'"><a href="#/realms/{{realm.realm}}/roles">Roles</a>
+    <li data-ng-show="access.viewRealm" data-ng-class="(path[2] == 'roles' || (path[1] == 'role' && path[3] != 'applications')) && 'active'"><a href="#/realms/{{realm.realm}}/roles">Roles</a>
     </li>
     <li data-ng-show="access.viewApplications" data-ng-class="(path[2] == 'applications' || path[1] == 'application' || path[3] == 'applications') && 'active'"><a href="#/realms/{{realm.realm}}/applications">Applications</a></li>
     <li data-ng-show="access.viewClients" data-ng-class="(path[2] == 'oauth-clients' || path[1] == 'oauth-client') && 'active'"><a href="#/realms/{{realm.realm}}/oauth-clients">OAuth Clients</a></li>
diff --git a/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java b/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java
index 68bf394..5a14b68 100755
--- a/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java
+++ b/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java
@@ -1,199 +1,199 @@
-/*
- * 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.services.resources.flows;
-
-import org.jboss.logging.Logger;
-import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
-import org.jboss.resteasy.spi.HttpRequest;
-import org.keycloak.ClientConnection;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.audit.Audit;
-import org.keycloak.audit.Details;
-import org.keycloak.audit.EventType;
-import org.keycloak.models.ApplicationModel;
-import org.keycloak.models.ClientModel;
-import org.keycloak.models.ClientSessionModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RequiredCredentialModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserModel.RequiredAction;
-import org.keycloak.models.UserSessionModel;
-import org.keycloak.representations.idm.CredentialRepresentation;
-import org.keycloak.services.managers.AccessCode;
-import org.keycloak.services.managers.AuthenticationManager;
-import org.keycloak.services.managers.TokenManager;
-
-import javax.ws.rs.core.Cookie;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.core.UriInfo;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-
-/**
- * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-public class OAuthFlows {
-
-    private static final Logger log = Logger.getLogger(OAuthFlows.class);
-
-    private final KeycloakSession session;
-
-    private final RealmModel realm;
-
-    private final HttpRequest request;
-
-    private final UriInfo uriInfo;
-
-    private ClientConnection clientConnection;
-    private final AuthenticationManager authManager;
-
-    private final TokenManager tokenManager;
-
-    OAuthFlows(KeycloakSession session, RealmModel realm, HttpRequest request, UriInfo uriInfo, ClientConnection clientConnection, AuthenticationManager authManager,
-            TokenManager tokenManager) {
-        this.session = session;
-        this.realm = realm;
-        this.request = request;
-        this.uriInfo = uriInfo;
-        this.clientConnection = clientConnection;
-        this.authManager = authManager;
-        this.tokenManager = tokenManager;
-    }
-
-    public Response redirectAccessCode(AccessCode accessCode, UserSessionModel userSession, String state, String redirect) {
-        String code = accessCode.getCode();
-        UriBuilder redirectUri = UriBuilder.fromUri(redirect).queryParam(OAuth2Constants.CODE, code);
-        log.debugv("redirectAccessCode: state: {0}", state);
-        if (state != null)
-            redirectUri.queryParam(OAuth2Constants.STATE, state);
-        Response.ResponseBuilder location = Response.status(302).location(redirectUri.build());
-        Cookie remember = request.getHttpHeaders().getCookies().get(AuthenticationManager.KEYCLOAK_REMEMBER_ME);
-
-        Cookie sessionCookie = request.getHttpHeaders().getCookies().get(AuthenticationManager.KEYCLOAK_SESSION_COOKIE);
-        if (sessionCookie != null) {
-            String oldSessionId = sessionCookie.getValue().split("/")[2];
-            if (!oldSessionId.equals(userSession.getId())) {
-                UserSessionModel oldSession = session.sessions().getUserSession(realm, oldSessionId);
-                if (oldSession != null) {
-                    log.debugv("Removing old user session: session: {0}", oldSessionId);
-                    session.sessions().removeUserSession(realm, oldSession);
-                }
-            }
-        }
-
-        // refresh the cookies!
-        authManager.createLoginCookie(realm, accessCode.getUser(), userSession, uriInfo, clientConnection);
-        if (userSession.isRememberMe()) authManager.createRememberMeCookie(realm, uriInfo, clientConnection);
-        return location.build();
-    }
-
-    public Response redirectError(ClientModel client, String error, String state, String redirect) {
-        UriBuilder redirectUri = UriBuilder.fromUri(redirect).queryParam(OAuth2Constants.ERROR, error);
-        if (state != null) {
-            redirectUri.queryParam(OAuth2Constants.STATE, state);
-        }
-        return Response.status(302).location(redirectUri.build()).build();
-    }
-
-    public Response processAccessCode(String scopeParam, String state, String redirect, ClientModel client, UserModel user, UserSessionModel session, Audit audit) {
-        isTotpConfigurationRequired(user);
-        isEmailVerificationRequired(user);
-
-        boolean isResource = client instanceof ApplicationModel;
-        AccessCode accessCode = tokenManager.createAccessCode(scopeParam, state, redirect, this.session, realm, client, user, session);
-
-        log.debugv("processAccessCode: isResource: {0}", isResource);
-        log.debugv("processAccessCode: go to oauth page?: {0}",
-                !isResource);
-
-        audit.detail(Details.CODE_ID, accessCode.getCodeId());
-
-        Set<RequiredAction> requiredActions = user.getRequiredActions();
-        if (!requiredActions.isEmpty()) {
-            RequiredAction action = user.getRequiredActions().iterator().next();
-            accessCode.setRequiredAction(action);
-
-            if (action.equals(RequiredAction.VERIFY_EMAIL)) {
-                audit.clone().event(EventType.SEND_VERIFY_EMAIL).detail(Details.EMAIL, accessCode.getUser().getEmail()).success();
-            }
-
-            return Flows.forms(this.session, realm, client, uriInfo).setAccessCode(accessCode.getCode()).setUser(user)
-                    .createResponse(action);
-        }
-
-        if (!isResource) {
-            accessCode.setAction(ClientSessionModel.Action.OAUTH_GRANT);
-
-            List<RoleModel> realmRoles = new LinkedList<RoleModel>();
-            MultivaluedMap<String, RoleModel> resourceRoles = new MultivaluedMapImpl<String, RoleModel>();
-            for (RoleModel r : accessCode.getRequestedRoles()) {
-                if (r.getContainer() instanceof RealmModel) {
-                    realmRoles.add(r);
-                } else {
-                    resourceRoles.add(((ApplicationModel) r.getContainer()).getName(), r);
-                }
-            }
-
-            return Flows.forms(this.session, realm, client, uriInfo)
-                    .setAccessCode(accessCode.getCode())
-                    .setAccessRequest(realmRoles, resourceRoles)
-                    .setClient(client)
-                    .createOAuthGrant();
-        }
-
-        if (redirect != null) {
-            audit.success();
-
-            accessCode.setAction(ClientSessionModel.Action.CODE_TO_TOKEN);
-            return redirectAccessCode(accessCode, session, state, redirect);
-        } else {
-            return null;
-        }
-    }
-
-    public Response forwardToSecurityFailure(String message) {
-        return Flows.forms(session, realm, null, uriInfo).setError(message).createErrorPage();
-    }
-
-    private void isTotpConfigurationRequired(UserModel user) {
-        for (RequiredCredentialModel c : realm.getRequiredCredentials()) {
-            if (c.getType().equals(CredentialRepresentation.TOTP) && !user.isTotp()) {
-                user.addRequiredAction(RequiredAction.CONFIGURE_TOTP);
-                log.debug("User is required to configure totp");
-            }
-        }
-    }
-
-    private void isEmailVerificationRequired(UserModel user) {
-        if (realm.isVerifyEmail() && !user.isEmailVerified()) {
-            user.addRequiredAction(RequiredAction.VERIFY_EMAIL);
-            log.debug("User is required to verify email");
-        }
-    }
-
-}
+/*
+ * 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.services.resources.flows;
+
+import org.jboss.logging.Logger;
+import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
+import org.jboss.resteasy.spi.HttpRequest;
+import org.keycloak.ClientConnection;
+import org.keycloak.OAuth2Constants;
+import org.keycloak.audit.Audit;
+import org.keycloak.audit.Details;
+import org.keycloak.audit.EventType;
+import org.keycloak.models.ApplicationModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RequiredCredentialModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserModel.RequiredAction;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.services.managers.AccessCode;
+import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.services.managers.TokenManager;
+
+import javax.ws.rs.core.Cookie;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class OAuthFlows {
+
+    private static final Logger log = Logger.getLogger(OAuthFlows.class);
+
+    private final KeycloakSession session;
+
+    private final RealmModel realm;
+
+    private final HttpRequest request;
+
+    private final UriInfo uriInfo;
+
+    private ClientConnection clientConnection;
+    private final AuthenticationManager authManager;
+
+    private final TokenManager tokenManager;
+
+    OAuthFlows(KeycloakSession session, RealmModel realm, HttpRequest request, UriInfo uriInfo, ClientConnection clientConnection, AuthenticationManager authManager,
+            TokenManager tokenManager) {
+        this.session = session;
+        this.realm = realm;
+        this.request = request;
+        this.uriInfo = uriInfo;
+        this.clientConnection = clientConnection;
+        this.authManager = authManager;
+        this.tokenManager = tokenManager;
+    }
+
+    public Response redirectAccessCode(AccessCode accessCode, UserSessionModel userSession, String state, String redirect) {
+        String code = accessCode.getCode();
+        UriBuilder redirectUri = UriBuilder.fromUri(redirect).queryParam(OAuth2Constants.CODE, code);
+        log.debugv("redirectAccessCode: state: {0}", state);
+        if (state != null)
+            redirectUri.queryParam(OAuth2Constants.STATE, state);
+        Response.ResponseBuilder location = Response.status(302).location(redirectUri.build());
+        Cookie remember = request.getHttpHeaders().getCookies().get(AuthenticationManager.KEYCLOAK_REMEMBER_ME);
+
+        Cookie sessionCookie = request.getHttpHeaders().getCookies().get(AuthenticationManager.KEYCLOAK_SESSION_COOKIE);
+        if (sessionCookie != null) {
+            String oldSessionId = sessionCookie.getValue().split("/")[2];
+            if (!oldSessionId.equals(userSession.getId())) {
+                UserSessionModel oldSession = session.sessions().getUserSession(realm, oldSessionId);
+                if (oldSession != null) {
+                    log.debugv("Removing old user session: session: {0}", oldSessionId);
+                    session.sessions().removeUserSession(realm, oldSession);
+                }
+            }
+        }
+
+        // refresh the cookies!
+        authManager.createLoginCookie(realm, accessCode.getUser(), userSession, uriInfo, clientConnection);
+        if (userSession.isRememberMe()) authManager.createRememberMeCookie(realm, uriInfo, clientConnection);
+        return location.build();
+    }
+
+    public Response redirectError(ClientModel client, String error, String state, String redirect) {
+        UriBuilder redirectUri = UriBuilder.fromUri(redirect).queryParam(OAuth2Constants.ERROR, error);
+        if (state != null) {
+            redirectUri.queryParam(OAuth2Constants.STATE, state);
+        }
+        return Response.status(302).location(redirectUri.build()).build();
+    }
+
+    public Response processAccessCode(String scopeParam, String state, String redirect, ClientModel client, UserModel user, UserSessionModel session, Audit audit) {
+        isTotpConfigurationRequired(user);
+        isEmailVerificationRequired(user);
+
+        boolean isResource = client instanceof ApplicationModel;
+        AccessCode accessCode = tokenManager.createAccessCode(scopeParam, state, redirect, this.session, realm, client, user, session);
+
+        log.debugv("processAccessCode: isResource: {0}", isResource);
+        log.debugv("processAccessCode: go to oauth page?: {0}",
+                !isResource);
+
+        audit.detail(Details.CODE_ID, accessCode.getCodeId());
+
+        Set<RequiredAction> requiredActions = user.getRequiredActions();
+        if (!requiredActions.isEmpty()) {
+            RequiredAction action = user.getRequiredActions().iterator().next();
+            accessCode.setRequiredAction(action);
+
+            if (action.equals(RequiredAction.VERIFY_EMAIL)) {
+                audit.clone().event(EventType.SEND_VERIFY_EMAIL).detail(Details.EMAIL, accessCode.getUser().getEmail()).success();
+            }
+
+            return Flows.forms(this.session, realm, client, uriInfo).setAccessCode(accessCode.getCode()).setUser(user)
+                    .createResponse(action);
+        }
+
+        if (!isResource) {
+            accessCode.setAction(ClientSessionModel.Action.OAUTH_GRANT);
+
+            List<RoleModel> realmRoles = new LinkedList<RoleModel>();
+            MultivaluedMap<String, RoleModel> resourceRoles = new MultivaluedMapImpl<String, RoleModel>();
+            for (RoleModel r : accessCode.getRequestedRoles()) {
+                if (r.getContainer() instanceof RealmModel) {
+                    realmRoles.add(r);
+                } else {
+                    resourceRoles.add(((ApplicationModel) r.getContainer()).getName(), r);
+                }
+            }
+
+            return Flows.forms(this.session, realm, client, uriInfo)
+                    .setAccessCode(accessCode.getCode())
+                    .setAccessRequest(realmRoles, resourceRoles)
+                    .setClient(client)
+                    .createOAuthGrant();
+        }
+
+        if (redirect != null) {
+            audit.success();
+
+            accessCode.setAction(ClientSessionModel.Action.CODE_TO_TOKEN);
+            return redirectAccessCode(accessCode, session, state, redirect);
+        } else {
+            return null;
+        }
+    }
+
+    public Response forwardToSecurityFailure(String message) {
+        return Flows.forms(session, realm, null, uriInfo).setError(message).createErrorPage();
+    }
+
+    private void isTotpConfigurationRequired(UserModel user) {
+        for (RequiredCredentialModel c : realm.getRequiredCredentials()) {
+            if (c.getType().equals(CredentialRepresentation.TOTP) && !user.isTotp()) {
+                user.addRequiredAction(RequiredAction.CONFIGURE_TOTP);
+                log.debug("User is required to configure totp");
+            }
+        }
+    }
+
+    private void isEmailVerificationRequired(UserModel user) {
+        if (realm.isVerifyEmail() && !user.isEmailVerified()) {
+            user.addRequiredAction(RequiredAction.VERIFY_EMAIL);
+            log.debug("User is required to verify email");
+        }
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/util/CookieHelper.java b/services/src/main/java/org/keycloak/services/util/CookieHelper.java
index 6d0d3a4..1b3b0e0 100755
--- a/services/src/main/java/org/keycloak/services/util/CookieHelper.java
+++ b/services/src/main/java/org/keycloak/services/util/CookieHelper.java
@@ -1,9 +1,15 @@
 package org.keycloak.services.util;
 
+import org.jboss.resteasy.spi.HttpResponse;
 import org.jboss.resteasy.spi.ResteasyProviderFactory;
 
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.HttpHeaders;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Locale;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -23,6 +29,14 @@ public class CookieHelper {
      * @param secure
      * @param httpOnly
      */
+    public static void addCookie2(String name, String value, String path, String domain, String comment, int maxAge, boolean secure, boolean httpOnly) {
+        HttpResponse response = ResteasyProviderFactory.getContextData(HttpResponse.class);
+        StringBuffer cookieBuf = new StringBuffer();
+        ServerCookie.appendCookieValue(cookieBuf, 1, name, value, path, domain, comment, maxAge, secure, httpOnly);
+        String cookie = cookieBuf.toString();
+        response.getOutputHeaders().add(HttpHeaders.SET_COOKIE, cookie);
+    }
+
     public static void addCookie(String name, String value, String path, String domain, String comment, int maxAge, boolean secure, boolean httpOnly) {
         HttpServletResponse response = ResteasyProviderFactory.getContextData(HttpServletResponse.class);
         Cookie cookie = new Cookie(name, value);
@@ -36,4 +50,6 @@ public class CookieHelper {
         response.addCookie(cookie);
 
     }
+
+
 }
diff --git a/services/src/main/java/org/keycloak/services/util/ServerCookie.java b/services/src/main/java/org/keycloak/services/util/ServerCookie.java
new file mode 100755
index 0000000..236da7e
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/util/ServerCookie.java
@@ -0,0 +1,347 @@
+package org.keycloak.services.util;
+
+import java.io.Serializable;
+import java.text.DateFormat;
+import java.text.FieldPosition;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+/**
+ * Server-side cookie representation.  borrowed from Tomcat.
+ */
+public class ServerCookie implements Serializable
+{
+   private static final String tspecials = ",; ";
+   private static final String tspecials2 = "()<>@,;:\\\"/[]?={} \t";
+
+   /*
+   * Tests a string and returns true if the string counts as a
+   * reserved token in the Java language.
+   *
+   * @param value the <code>String</code> to be tested
+   *
+   * @return      <code>true</code> if the <code>String</code> is a reserved
+   *              token; <code>false</code> if it is not
+   */
+   public static boolean isToken(String value)
+   {
+      if (value == null) return true;
+      int len = value.length();
+
+      for (int i = 0; i < len; i++)
+      {
+         char c = value.charAt(i);
+
+         if (tspecials.indexOf(c) != -1)
+            return false;
+      }
+      return true;
+   }
+
+   public static boolean containsCTL(String value, int version)
+   {
+      if (value == null) return false;
+      int len = value.length();
+      for (int i = 0; i < len; i++)
+      {
+         char c = value.charAt(i);
+         if (c < 0x20 || c >= 0x7f)
+         {
+            if (c == 0x09)
+               continue; //allow horizontal tabs
+            return true;
+         }
+      }
+      return false;
+   }
+
+
+   public static boolean isToken2(String value)
+   {
+      if (value == null) return true;
+      int len = value.length();
+
+      for (int i = 0; i < len; i++)
+      {
+         char c = value.charAt(i);
+         if (tspecials2.indexOf(c) != -1)
+            return false;
+      }
+      return true;
+   }
+
+   /**
+    * @deprecated - Not used
+    */
+   public static boolean checkName(String name)
+   {
+      if (!isToken(name)
+              || name.equalsIgnoreCase("Comment")     // rfc2019
+              || name.equalsIgnoreCase("Discard")     // rfc2965
+              || name.equalsIgnoreCase("Domain")      // rfc2019
+              || name.equalsIgnoreCase("Expires")     // Netscape
+              || name.equalsIgnoreCase("Max-Age")     // rfc2019
+              || name.equalsIgnoreCase("Path")        // rfc2019
+              || name.equalsIgnoreCase("Secure")      // rfc2019
+              || name.equalsIgnoreCase("Version")     // rfc2019
+         // TODO remaining RFC2965 attributes
+              )
+      {
+         return false;
+      }
+      return true;
+   }
+
+   // -------------------- Cookie parsing tools
+
+
+   /**
+    * Return the header name to set the cookie, based on cookie version.
+    */
+   public static String getCookieHeaderName(int version)
+   {
+      // TODO Re-enable logging when RFC2965 is implemented
+      // log( (version==1) ? "Set-Cookie2" : "Set-Cookie");
+      if (version == 1)
+      {
+         // XXX RFC2965 not referenced in Servlet Spec
+         // Set-Cookie2 is not supported by Netscape 4, 6, IE 3, 5
+         // Set-Cookie2 is supported by Lynx and Opera
+         // Need to check on later IE and FF releases but for now...
+         // RFC2109
+         return "Set-Cookie";
+         // return "Set-Cookie2";
+      }
+      else
+      {
+         // Old Netscape
+         return "Set-Cookie";
+      }
+   }
+
+   /**
+    * US locale - all HTTP dates are in english
+    */
+   private final static Locale LOCALE_US = Locale.US;
+
+   /**
+    * GMT timezone - all HTTP dates are on GMT
+    */
+   public final static TimeZone GMT_ZONE = TimeZone.getTimeZone("GMT");
+   /**
+    * Pattern used for old cookies
+    */
+   private final static String OLD_COOKIE_PATTERN = "EEE, dd-MMM-yyyy HH:mm:ss z";
+
+
+   private final static DateFormat oldCookieFormat = new SimpleDateFormat(OLD_COOKIE_PATTERN, LOCALE_US);
+
+   public static String formatOldCookie(Date d)
+   {
+      String ocf = null;
+      synchronized (oldCookieFormat)
+      {
+         ocf = oldCookieFormat.format(d);
+      }
+      return ocf;
+   }
+
+   public static void formatOldCookie(Date d, StringBuffer sb,
+                                      FieldPosition fp)
+   {
+      synchronized (oldCookieFormat)
+      {
+         oldCookieFormat.format(d, sb, fp);
+      }
+   }
+
+
+   private static final String ancientDate = formatOldCookie(new Date(10000));
+
+
+   // TODO RFC2965 fields also need to be passed
+   public static void appendCookieValue(StringBuffer headerBuf,
+                                        int version,
+                                        String name,
+                                        String value,
+                                        String path,
+                                        String domain,
+                                        String comment,
+                                        int maxAge,
+                                        boolean isSecure,
+                                        boolean httpOnly)
+   {
+      StringBuffer buf = new StringBuffer();
+      // Servlet implementation checks name
+      buf.append(name);
+      buf.append("=");
+      // Servlet implementation does not check anything else
+
+      maybeQuote2(version, buf, value);
+
+      // Add version 1 specific information
+      if (version == 1)
+      {
+         // Version=1 ... required
+         buf.append("; Version=1");
+
+         // Comment=comment
+         if (comment != null)
+         {
+            buf.append("; Comment=");
+            maybeQuote2(version, buf, comment);
+         }
+      }
+
+      // Add domain information, if present
+      if (domain != null)
+      {
+         buf.append("; Domain=");
+         maybeQuote2(version, buf, domain);
+      }
+
+      // Max-Age=secs ... or use old "Expires" format
+      // TODO RFC2965 Discard
+      if (maxAge >= 0)
+      {
+          // Wdy, DD-Mon-YY HH:MM:SS GMT ( Expires Netscape format )
+          buf.append("; Expires=");
+          // To expire immediately we need to set the time in past
+          if (maxAge == 0)
+              buf.append(ancientDate);
+          else
+              formatOldCookie
+                      (new Date(System.currentTimeMillis() +
+                                      maxAge * 1000L), buf,
+                              new FieldPosition(0));
+
+          buf.append("; Max-Age=");
+          buf.append(maxAge);
+      }
+
+      // Path=path
+      if (path != null)
+      {
+         buf.append("; Path=");
+         buf.append(path);
+      }
+
+       // Secure
+       if (isSecure)
+       {
+           buf.append("; Secure");
+       }
+
+       // HttpOnly
+       if (httpOnly)
+       {
+           buf.append("; HttpOnly");
+       }
+
+       headerBuf.append(buf);
+   }
+
+   /**
+    * @deprecated - Not used
+    */
+   @Deprecated
+   public static void maybeQuote(int version, StringBuffer buf, String value)
+   {
+      // special case - a \n or \r  shouldn't happen in any case
+      if (isToken(value))
+      {
+         buf.append(value);
+      }
+      else
+      {
+         buf.append('"');
+         buf.append(escapeDoubleQuotes(value, 0, value.length()));
+         buf.append('"');
+      }
+   }
+
+   public static boolean alreadyQuoted(String value)
+   {
+      if (value == null || value.length() == 0) return false;
+      return (value.charAt(0) == '\"' && value.charAt(value.length() - 1) == '\"');
+   }
+
+   /**
+    * Quotes values using rules that vary depending on Cookie version.
+    *
+    * @param version
+    * @param buf
+    * @param value
+    */
+   public static void maybeQuote2(int version, StringBuffer buf, String value)
+   {
+      if (value == null || value.length() == 0)
+      {
+         buf.append("\"\"");
+      }
+      else if (containsCTL(value, version))
+         throw new IllegalArgumentException("Control character in cookie value, consider BASE64 encoding your value");
+      else if (alreadyQuoted(value))
+      {
+         buf.append('"');
+         buf.append(escapeDoubleQuotes(value, 1, value.length() - 1));
+         buf.append('"');
+      }
+      else if (version == 0 && !isToken(value))
+      {
+         buf.append('"');
+         buf.append(escapeDoubleQuotes(value, 0, value.length()));
+         buf.append('"');
+      }
+      else if (version == 1 && !isToken2(value))
+      {
+         buf.append('"');
+         buf.append(escapeDoubleQuotes(value, 0, value.length()));
+         buf.append('"');
+      }
+      else
+      {
+         buf.append(value);
+      }
+   }
+
+
+   /**
+    * Escapes any double quotes in the given string.
+    *
+    * @param s          the input string
+    * @param beginIndex start index inclusive
+    * @param endIndex   exclusive
+    * @return The (possibly) escaped string
+    */
+   private static String escapeDoubleQuotes(String s, int beginIndex, int endIndex)
+   {
+
+      if (s == null || s.length() == 0 || s.indexOf('"') == -1)
+      {
+         return s;
+      }
+
+      StringBuffer b = new StringBuffer();
+      for (int i = beginIndex; i < endIndex; i++)
+      {
+         char c = s.charAt(i);
+         if (c == '\\')
+         {
+            b.append(c);
+            //ignore the character after an escape, just append it
+            if (++i >= endIndex) throw new IllegalArgumentException("Invalid escape character in cookie value.");
+            b.append(s.charAt(i));
+         }
+         else if (c == '"')
+            b.append('\\').append('"');
+         else
+            b.append(c);
+      }
+
+      return b.toString();
+   }
+
+}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/FederationProvidersIntegrationTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/FederationProvidersIntegrationTest.java
index 99f6558..9b48590 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/FederationProvidersIntegrationTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/FederationProvidersIntegrationTest.java
@@ -3,6 +3,7 @@ package org.keycloak.testsuite.forms;
 import org.junit.Assert;
 import org.junit.ClassRule;
 import org.junit.FixMethodOrder;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.RuleChain;
@@ -102,6 +103,13 @@ public class FederationProvidersIntegrationTest {
     @WebResource
     protected AccountPasswordPage changePasswordPage;
 
+    @Test
+    @Ignore
+    public void runit() throws Exception {
+        Thread.sleep(10000000);
+
+    }
+
     static UserModel addUser(KeycloakSession session, RealmModel realm, String username, String email, String password) {
         UserModel user = session.users().addUser(realm, username);
         user.setEmail(email);