Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SpringSecurity: Fail to delete JSESSIONID

I need to delete the cookie JSESSIONID when the user logs out. To do that I have added the following configuration to my security config:

<http>
    <form-login login-page="/login*" authentication-failure-url="/login?try_again" />
    <http-basic />
    <logout logout-url="/logout" delete-cookies="JSESSIONID" />
    <session-management invalid-session-url="/timeout" />

    <intercept-url pattern="/login*"    access="IS_AUTHENTICATED_ANONYMOUSLY" />

    ...

</http>

But instead of being deleted, the cookie is just became duplicated:

Old cookie

New cookie

So it keeps redirecting the browser to the "/timeout" URL.

I tried to trace what's going on using the Developer Tools in Chrome web browser, and I found out that this cookie sets up with this response header:

Set-Cookie:JSESSIONID=CFF85EA743724F23FDA0317A75CFAD44; Path=/website/; HttpOnly

And deletes with this response header:

Set-Cookie:JSESSIONID=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/website

I'm not sure, but it seems like the reason is in the "Path" field of these headers: in the first one it points to "/website/", and in the second one it points to "/website".

Is it the reason of the described trouble? If it's not the reason (or not the only reason), what is the other reason(s)? How should I fix this trouble?

like image 897
user1764823 Avatar asked Apr 11 '13 10:04

user1764823


2 Answers

You don't need to explicitly delete the JSESSIONID cookie like this. It is not managed by Spring Security as such, but by your servlet container. Spring Security will by default invalidate the http session upon logout, which in turn causes your servlet container to remove the JSESSIONID cookie.

like image 159
zagyi Avatar answered Sep 29 '22 04:09

zagyi


In my case for some reason even though SecurityContextLogoutHandler calls session.invalidate() JSESSIONID wouldn't be cleared. Its value remained the same.

I tried to use delete-cookies="JSESSIONID" the same way the OP tried, and I believe I had the same problem: The path set for the cookie was the context path without a / at the end, so it still wouldn't be cleared (It was giving the order to delete a cookie that didn't exist).

I ended up writing my own ProperCookieClearLogoutHandler, which is identic to CookieClearingLogoutHandler except for the line that sets the context path for the cookie:

package com.testdomain.testpackage;

import java.util.Arrays;
import java.util.List;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

public final class ProperCookieClearingLogoutHandler implements LogoutHandler {
    private final List<String> cookiesToClear;

    public ProperCookieClearingLogoutHandler(String... cookiesToClear) {
        Assert.notNull(cookiesToClear, "List of cookies cannot be null");
        this.cookiesToClear = Arrays.asList(cookiesToClear);
    }

    public void logout(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) {
        for (String cookieName : cookiesToClear) {
            Cookie cookie = new Cookie(cookieName, null);
            String cookiePath = request.getContextPath() + "/";
            if (!StringUtils.hasLength(cookiePath)) {
                cookiePath = "/";
            }
            cookie.setPath(cookiePath);
            cookie.setMaxAge(0);
            response.addCookie(cookie);
        }
    }
}

Then I set the config for the LogoutFilter on spring-security.xml this way;

    <bean id="logoutFilter"
        class="org.springframework.security.web.authentication.logout.LogoutFilter">
        <constructor-arg name="logoutSuccessUrl" value="/views/login/login.xhtml?logout" />
        <constructor-arg>
            <list>
                <bean id="properCookieClearingLogoutHandler"
                    class="com.imatia.arpad.gplenos.authorization.ProperCookieClearingLogoutHandler">
                    <constructor-arg name="cookiesToClear">
                        <list>
                            <value>JSESSIONID</value>
                        </list>
                    </constructor-arg>
                </bean>
                <bean id="securityContextLogoutHandler"
                    class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler">
                </bean>
            </list>
        </constructor-arg>
        <property name="filterProcessesUrl" value="/logout" />
    </bean>
like image 35
NotGaeL Avatar answered Sep 29 '22 03:09

NotGaeL