Spring Security RememberMe Services with Session Cookie

authenticationremember-meSecurityspringspring-security

I am using Spring Security's RememberMe Services to keep a user authenticated.

I would like to find a simple way to have the RememberMe cookie set as a session cookie rather than with a fixed expiration time. For my application, the cookie should persist until the user closes the browser.

Any suggestions on how to best implement this? Any concerns on this being a potential security problem?

The primary reason for doing so is that with a cookie-based token, any of the servers behind our load balancer can service a protected request without relying on the user's Authentication to be stored in an HttpSession. In fact, I have explicitly told Spring Security to never create sessions using the namespace. Further, we are using Amazon's Elastic Load Balancing, and so sticky sessions are not supported.

NB: Although I am aware that as of Apr. 08, Amazon now supports sticky sessions, I still do not want to use them for a handful of other reasons. Namely that the untimely demise of one server would still cause the loss of sessions for all users associated with it.
http://aws.amazon.com/about-aws/whats-new/2010/04/08/support-for-session-stickiness-in-elastic-load-balancing/

Best Answer

Spring Security 3 does not offer configuration of how the cookie is generated. You have to override the default behaviour:

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices;

/** Cookie expires on session. */
 public class PersistentTokenBasedRememberMeServicesCustom extends
   PersistentTokenBasedRememberMeServices {

  /** only needed because super throws exception. */
  public PersistentTokenBasedRememberMeServicesCustom() throws Exception {
    super();
  }

  /** Copy of code of inherited class + setting cookieExpiration, */
  @Override
  protected void setCookie(String[] tokens, int maxAge,
      HttpServletRequest request, HttpServletResponse response) {
    String cookieValue = encodeCookie(tokens);
    Cookie cookie = new Cookie(getCookieName(), cookieValue);
    //cookie.setMaxAge(maxAge); 
    cookie.setPath("/");
    cookie.setSecure(false); // no getter available in super, so always false

    response.addCookie(cookie);
  }
}

Make sure, you use this customized PersistentTokenBasedRememberMeServices for you're rememberMeService by adding the class name to it's bean configuration:

<beans:bean id="rememberMeServices"
 class="my.custom.spring.PersistentTokenBasedRememberMeServicesCustom"/>