I'm upgrading a working application from Spring Boot 2.6.5 to 2.7.8 (Spring Security 5.7.6) so that I can better upgrade to 3.0.
Logout was working fine before. But after upgrading to Sprint Boot 2.7.8 the logout handling is hanging and never redirecting to the logoutSuccessUrl()
.
Here is the complete filter chain configuration:
http
.authorizeHttpRequests((authz) -> authz
.antMatchers("/webjars/**","/login/**","/mobile-manifest.json","/service-worker.js","/cache.manifest","/favicon.ico","/async/**","/api/**").permitAll()
.anyRequest().authenticated()
)
.httpBasic(withDefaults())
.formLogin(formLogin -> formLogin
.loginPage("/login")
.permitAll()
.loginProcessingUrl("/login")
.successHandler(savedRequestAwareAuthenticationSuccessHandler())
.failureUrl("/login?loginFailed=true"))
.logout( logout -> logout
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logoutSuccess=true")
.invalidateHttpSession(true)
.deleteCookies(COOKIE_STRING))
.rememberMe( rememberMe -> rememberMe
.key(TOKEN_KEY)
.rememberMeParameter(REMEMBER_ME_KEY)
.tokenRepository(persistentTokenRepository())
.userDetailsService(userSvc)
.tokenValiditySeconds(validitySeconds));
The output:
[https-jsse-nio-7001-exec-10] [DEBUG] [o.s.security.web.FilterChainProxy] - Securing POST /logout
[https-jsse-nio-7001-exec-10] [DEBUG] [o.s.s.w.c.HttpSessionSecurityContextRepository] - Retrieved SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=UserProfile [ blah blah, eventRoles=null, lastLoginDisplay=today, directoryUrl=null, groups=[]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=740230E1C02B57BEF504C23570FFA9EC], Granted Authorities=[]]]
[https-jsse-nio-7001-exec-10] [DEBUG] [o.s.s.w.c.SecurityContextPersistenceFilter] - Set SecurityContextHolder to SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=UserProfile [blah blah eventRoles=null, lastLoginDisplay=today, directoryUrl=null, groups=[]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=740230E1C02B57BEF504C23570FFA9EC], Granted Authorities=[]]]
[https-jsse-nio-7001-exec-10] [DEBUG] [o.s.s.w.a.logout.LogoutFilter] - Logging out [UsernamePasswordAuthenticationToken [Principal=UserProfile [blah blah, eventRoles=null, lastLoginDisplay=today, directoryUrl=null, groups=[]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=740230E1C02B57BEF504C23570FFA9EC], Granted Authorities=[]]]
[https-jsse-nio-7001-exec-10] [DEBUG] [o.s.s.w.a.r.PersistentTokenBasedRememberMeServices] - Logout of user username
[https-jsse-nio-7001-exec-10] [DEBUG] [o.s.s.w.a.r.PersistentTokenBasedRememberMeServices] - Cancelling cookie
[https-jsse-nio-7001-exec-10] [DEBUG] [o.s.jdbc.core.JdbcTemplate] - Executing prepared SQL update
[https-jsse-nio-7001-exec-10] [DEBUG] [o.s.jdbc.core.JdbcTemplate] - Executing prepared SQL statement [delete from persistent_logins where username = ?]
[https-jsse-nio-7001-exec-10] [DEBUG] [o.s.jdbc.datasource.DataSourceUtils] - Fetching JDBC Connection from DataSource
[https-jsse-nio-7001-exec-10] [DEBUG] [o.s.s.w.a.l.SecurityContextLogoutHandler] - Invalidated session F3BC69312EC05C175A0FCEC298B49D06
[https-jsse-nio-7001-exec-10] [DEBUG] [o.s.s.w.c.HttpSessionSecurityContextRepository] - Did not store empty SecurityContext
[https-jsse-nio-7001-exec-10] [DEBUG] [o.s.s.w.c.HttpSessionSecurityContextRepository] - Did not store empty SecurityContext
[https-jsse-nio-7001-exec-10] [DEBUG] [o.s.s.w.c.SecurityContextPersistenceFilter] - Cleared SecurityContextHolder to complete request
Browser is never redirected to the loginSuccessUrl()
, all DEBUG logging ends above. CSRF is enabled and logout was submitted POST
.
I had .permitAll()
in the logout configuration, but it seemed to have no effect in this case.
Screenshot showing request / response
CodePudding user response:
Spring Security provides two implementations of LogoutSuccessHandler
, see LogoutSuccessHandler:
LogoutSuccessHandler
The
LogoutSuccessHandler
is called after a successful logout by theLogoutFilter
, to handle (for example) redirection or forwarding to the appropriate destination. Note that the interface is almost the same as theLogoutHandler
but may raise an exception.Spring Security provides the following implementations:
SimpleUrlLogoutSuccessHandler
HttpStatusReturningLogoutSuccessHandler
As mentioned earlier, you need not specify the
SimpleUrlLogoutSuccessHandler
directly. Instead, the fluent API provides a shortcut by setting thelogoutSuccessUrl()
. This sets up theSimpleUrlLogoutSuccessHandler
under the covers. The provided URL is redirected to after a logout has occurred. The default is/login?logout
.The
HttpStatusReturningLogoutSuccessHandler
can be interesting in REST API type scenarios. Instead of redirecting to a URL upon the successful logout, thisLogoutSuccessHandler
lets you provide a plain HTTP status code to be returned. If not configured, a status code 200 is returned by default.
If you configure HTTP basic authentication, the HttpStatusReturningLogoutSuccessHandler
is added, see
Default Logout Handler with HTTP Basic and XMLHttpRequest should be 204:
The default behavior for logout when the header X-Requested-With: XMLHttpRequest and HTTP Basic is enabled should be a 201. This will improve AngularJS experience which sends an accept header which includes text/html
See also: SEC-3103: Logout Success Content Negotiation.