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/
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"/>