1

How in Spring Security can I set a RememberMe cookie url path, that differs from the context path?

Supposing my website's homepage url is (url rewrite):

https://www.mysuperspecialdomain.com

And that my login page has a url like this:

https://www.mysuperspecialdomain.com/shop/account/login

After succesful login the RememberMe cookie has the path /shop (visible in the browser, e.g. Chrome). This is the project's context path.

This leads to the situation, that when I'm going to my homepage, RememberMe is not logging in. Only when I navigate to a url, that starts with https://www.myspecialdomain.com/shop it's doing it.

olivmir
  • 692
  • 10
  • 29

2 Answers2

2

If you use Spring Security 4.1.0 or higher, you can configure the cookie domain, see RememberMeConfigurer#rememberMeCookieDomain:

The domain name within which the remember me cookie is visible.

but you can't change the context path.

So you have to implement your own RememberMeServices (you could create a sub class of an existing one) and add it with RememberMeConfigurer#rememberMeServices to your security configuration.

dur
  • 15,689
  • 25
  • 79
  • 125
  • 1
    Thank you. You are right. But instead of implementing a new `RememberMeService`, I prefer to extend an existing like `TokenBasedRememberMeServices`. [In this link](http://stackoverflow.com/questions/16015468/how-to-change-grails-spring-security-cookie-path) that is described. My great concern: as soon, as I would use a new Spring version, I would have to check, if the `setCookie` method has been implemented as in my extended version. Spring should offer an option to configure this ... – olivmir Dec 08 '16 at 15:30
  • 1
    I've found a solution to my own question: [go to this](http://stackoverflow.com/a/41117823/7095884). The advantage is, that you don't have to change the Spring RememberMeService-implementation. – olivmir Dec 13 '16 at 09:43
2

I've found a solution to my own question - manipulation of the path of the RememberMe-cookie can be done via an HttpServletResponseWrapper. This is the solution (based on this answer https://stackoverflow.com/a/7047298/7095884):

  1. Define an HttpServletResponseWrapper:

    public class RememberMeCookieResponseWrapper extends HttpServletResponseWrapper {
        public RememberMeCookieResponseWrapper(HttpServletResponse response) {
            super(response);
        }
    
        @Override
        public void addCookie(Cookie cookie) {
            if (cookie.getName().equals("shop")) {
                cookie.setPath("/");
            }
            super.addCookie(cookie);
        }
    }
    
  2. Define a filter, that wraps the servlet response with the just defined wrapper:

    public class RememberMeCookieFilter implements Filter {
    
        public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain) throws IOException, ServletException {
    
            if (response instanceof HttpServletResponse) {
                HttpServletResponse newResponse =
                    new RememberMeCookieResponseWrapper((HttpServletResponse)response);
                chain.doFilter(request, newResponse);
            }
        }
    }
    
  3. Add this filter to the Spring Filter Chain in front of the authentication part:

    @Configuration
    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
         @Override
        protected void configure(HttpSecurity http) throws Exception {
    
            http.addFilterBefore(new RememberMeCookieFilter(), UsernamePasswordAuthenticationFilter.class)
            ...
    
Community
  • 1
  • 1
olivmir
  • 692
  • 10
  • 29