0

I have a HTML form that issues REST API calls to a Spring Boot backend. I'm using Spring Session to handle concurrent logins by the same user. If I use expiredUrl in the below code, I get redirected to the login.html page when the current session has expired. This works fine when I click on menu items that request for a HTML page.

If I'm already on a page and I click a button that issues an AJAX call to the server, I get a 302(fetch/Redirect) status followed by the login.html page with a 200 status when the session has expired. So the Ajax call is getting a response of 200, which is not correct. I replaced expiredUrl with expiredSessionStrategy in the code below, but expiredSessionStrategy is not getting invoked at all. If any of you know the reason or see a flaw in my code, please let me know. I searched the spring session documentation for expiredSessionStrategy, but was not able to find anything.

I found a couple of articles on stackoverflow that suggest using AjaxAwareAuthenticationEntryPoint to get a custom response for an Ajax call on session expiry. I will try this approach, but I would like to know why expiredSessionStrategy is not getting called in my case.

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    
        http
         .csrf(..)
         .authorizeHttpRequests(..)
         .oauth2Login(oauth2 -> { 
                oauth2
               .userInfoEndpoint(userInfo -> userInfo
                                    .oidcUserService(this.oidcUserService())
                                 )
               .loginPage("/login.html") 
               .failureUrl("/loginFailure")
               .successHandler(customOauth2SuccessHandler) ;
                            }
        )
        .logout(...)
        .sessionManagement((sessions) -> sessions
                                        .maximumSessions(1)
                                        .sessionRegistry(this.sessionRegistry())
                                        .expiredSessionStrategy( event -> 
                                            {
                                                String URI = event.getRequest().getRequestURI();
                                                System.out.println("URI="+URI);
                                                if (URI.endsWith(".html"))
                                                    event.getResponse().sendRedirect("/login.html?msgCode=4");
                                                else
                                                {
                                                    event.getResponse().setContentType("application/json");
                                                    event.getResponse().sendError(440, "Session has expired. Please login again !");    
                                                }
                                            } 
                                        )
                                        //.expiredUrl("/login.html?msgCode=4")      
                        );

    return http.build();
}

1 Answer 1

0

I turned trace on for the spring security packages and this is what I discovered. When a session expires, spring session management is deleting the expired session. There may be properties that you can set to control this behaviour, but I have not looked into it. When my application issued the Ajax API request, the expired session cookie was sent to the server along with the request. Since the session had already been deleted by Spring, it was treated as an invalid session and not an expired session. So I used invalidSessionStrategy instead of expiredSessionStrategy and things worked for me. I created a new implementation of the InvalidSessionStrategy interface and made it send a JSON response for Ajax API requests. You will need to implement expiredSessionStrategy also because the cleanup job may not yet have run and the expired session could still be there.

One mistake from my side was that I thought that expiredURL was working and hence I was stumped that expiredSessionStrategy was not getting invoked. Actually, expiredURL was never getting called. The default behaviour is to redirect to the login page when Spring detects an invalid session. Since expiredURL was also redirecting to the login page in my case, I thought that expiredURL was working and again that was a mistake from my side and I'm really sorry if that misled any of you.

Not the answer you're looking for? Browse other questions tagged or ask your own question.