4
votes

As per the post Spring Security: Redirect to invalid-session-url instead of logout-success-url on successful logout, when logging out of a session Spring Security redirects to the user defined invalid-session-url.

<session-management invalid-session-url="/invalidSession.jsp">
    <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
</session-management> 

However, if a logout-success url is set

<logout invalidate-session="true" 
            logout-success-url="/logoutSuccess.jsp" 
            logout-url="/logout" />

Spring still redirects to the invalid session URL after redirecting to the logout-success url. This happens even when the logoutSuccess url is unsecured. I.e.,

<intercept-url pattern="/logoutSuccess.jsp*" access="permitAll"/> 

Is this a Spring bug? Since the logout-success-url is set and unsecured it seems that the user should not be redirected to invalid session url after reaching the logout success url.

The log looks as follows:

INFO: [DEBUG,SimpleUrlLogoutSuccessHandler] Using default Url: /logoutSuccess.jsp
INFO: [DEBUG,DefaultRedirectStrategy] Redirecting to '/Application/logoutSuccess.jsp'
INFO: [DEBUG,HttpSessionSecurityContextRepository] SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
INFO: [DEBUG,SecurityContextPersistenceFilter] SecurityContextHolder now cleared, as request processing completed
INFO: [DEBUG,FilterChainProxy] /logoutSuccess.jsp at position 1 of 10 in additional filter chain; firing Filter: 'ConcurrentSessionFilter'
INFO: [DEBUG,FilterChainProxy] /logoutSuccess.jsp at position 2 of 10 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
INFO: [DEBUG,HttpSessionSecurityContextRepository] No HttpSession currently exists
INFO: [DEBUG,HttpSessionSecurityContextRepository] No SecurityContext was available from the HttpSession: null. A new one will be created.
INFO: [DEBUG,FilterChainProxy] /logoutSuccess.jsp at position 3 of 10 in additional filter chain; firing Filter: 'LogoutFilter'
INFO: [DEBUG,FilterChainProxy] /logoutSuccess.jsp at position 4 of 10 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
INFO: [DEBUG,FilterChainProxy] /logoutSuccess.jsp at position 5 of 10 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
INFO: [DEBUG,FilterChainProxy] /logoutSuccess.jsp at position 6 of 10 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
INFO: [DEBUG,FilterChainProxy] /logoutSuccess.jsp at position 7 of 10 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
INFO: [DEBUG,AnonymousAuthenticationFilter] Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
INFO: [DEBUG,FilterChainProxy] /logoutSuccess.jsp at position 8 of 10 in additional filter chain; firing Filter: 'SessionManagementFilter'
INFO: [DEBUG,SessionManagementFilter] Requested session ID a396530a530b344ff531ab657e32 is invalid.
INFO: [DEBUG,SimpleRedirectInvalidSessionStrategy] Starting new session (if required) and redirecting to '/invalidsession.jsp'
INFO: [DEBUG,HttpSessionEventPublisher] Publishing event: org.springframework.security.web.session.HttpSessionCreatedEvent[source=org.apache.catalina.session.StandardSessionFacade@564c4200]
INFO: [DEBUG,DefaultRedirectStrategy] Redirecting to '/Application/invalidsession.jsp'
3

3 Answers

7
votes

This is explained in the reference manual.

To summarise, the "invalid session" functionality is based on the validity of the submitted session cookie, so if you access the site (or more specifically, the security filter chain) after logging out, and you still have a JSESSIONID cookie, you may trigger this undesired behaviour.

As described in the same part of the manual, you can try using

<logout invalidate-session="true" 
        logout-success-url="/logoutSuccess.jsp" 
        logout-url="/logout" delete-cookies="JSESSIONID" />

to remove the cookie when logging out.

2
votes

You must take care, sometimes using invalidate-session='true' and delete-cookies=JSESSIONID together along with limited number of sessions that a user can have, might get you "Maximum sessions of 1 for this principal exceeded" error when you try to log in even after you log out.

It is advisable to use only Delete-cookies to remove necessary session information when u are using Spring Security 3.1 and above.

0
votes

Configure the logout as below to delete cookies in the security configure WebSecurityConfigurerAdapter class.

 @Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
    //set access to all pages including session time out page where session time out is set in the application.properties page
       httpSecurity
            .authorizeRequests().antMatchers("/","/products","/product/show/*","/session","/console/*","/h2-console/**").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin().loginPage("/login").permitAll()
            .and()
            .logout().permitAll();
       //delete cookies so it won't get forwarded to session out page
       httpSecurity.logout().deleteCookies("auth_code", "JSESSIONID").invalidateHttpSession(true);                          

    httpSecurity.csrf().disable();
    httpSecurity.headers().frameOptions().disable();
   httpSecurity.sessionManagement().invalidSessionUrl("/session");
}

And finally in the session expiration forward page delete the cookies manually

 @RequestMapping("/session")
String session(HttpServletRequest request,HttpServletResponse response){
    SecurityContextHolder.clearContext();
    HttpSession session= request.getSession(false);
    Cookie[] cookies = request.getCookies();
    // Delete all the cookies
    if (cookies != null) {
             for (int i = 0; i < cookies.length; i++) {
            Cookie cookie = cookies[i];
            cookies[i].setValue(null);
            cookies[i].setMaxAge(0);
            response.addCookie(cookie);
        }
    }
    SecurityContextHolder.clearContext();
    if(session != null) {
        session.invalidate();
    }
    return "session";
}