I understand this question has been asked before, but none of what worked for the others worked for me. That said, here it is:
After setting up .logout()
and its relevant associate methods, I still cannot make my Spring server logout properly. To be precise, this is the sequence I'm following:
POST
login, get token- Use token for other HTTP requests, such as a standard
GET
for DB data - Logout using the vanilla logout URL
- Try to do step 2 again, to see if logout was successful.
At 4, for a reason that is unknown to me, I'm still able to
GET
the data, which is wrong.
Some of the things I've tried are:
.clearAuthentication(true).invalidateHttpSession(true)
- Setting up the following bean on my
SecurityConfig
:
@Bean
public static ServletListenerRegistrationBean httpSessionEventPublisher() {
return new ServletListenerRegistrationBean(new HttpSessionEventPublisher());
}
None of it worked. Below are my security configurations. Any clues and help is much appreciated, and I thank you in advance.
SecurityConfig.java
@Configuration
public class SecurityConfig {
@Autowired
private AuthenticationManager authenticationManager;
private final AuthSuccessHandler authSuccessHandler;
private final JwtUserDetailsService jwtUserDetailsService;
private final String secret;
SecurityConfig(AuthSuccessHandler authSuccessHandler, JwtUserDetailsService jwtUserDetailsService, @Value("${jwt.secret}") String secret) {
this.authSuccessHandler = authSuccessHandler;
this.jwtUserDetailsService = jwtUserDetailsService;
this.secret = secret;
}
@Bean
public static ServletListenerRegistrationBean httpSessionEventPublisher() {
return new ServletListenerRegistrationBean(new HttpSessionEventPublisher());
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf()
.disable()
.authorizeHttpRequests((auth) -> {
try {
auth
.requestMatchers("/user").hasRole("USER")
.requestMatchers("/admin").hasRole("ADMIN")
.requestMatchers("**/encoding-results/**", "**/encoding-results").hasAnyRole("ADMIN")
.requestMatchers("**/video/**").hasAnyRole("ADMIN")
.requestMatchers("**/codec/**").hasAnyRole("ADMIN")
.requestMatchers("**/auth/**").permitAll()
.anyRequest().authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilter(authenticationFilter())
.addFilter(new JwtAuthorizationFilter(authenticationManager, jwtUserDetailsService, secret))
.logout(logout -> logout
.clearAuthentication(true)
.logoutUrl("/logout")
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID"))
.exceptionHandling()
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
} catch (Exception e) {
throw new RuntimeException(e);
}
})
.httpBasic(Customizer.withDefaults());
return http.build();
}
@Bean
public JsonObjectAuthenticationFilter authenticationFilter() throws Exception {
JsonObjectAuthenticationFilter filter = new JsonObjectAuthenticationFilter();
filter.setAuthenticationSuccessHandler(authSuccessHandler);
filter.setAuthenticationManager(authenticationManager);
return filter;
}
}
CodePudding user response:
You cant logout a JWT, a JWT is valid as long as you have set the validation time to be.
OWASP has written about this problem No Built-In Token Revocation by the User
You have written a custom login that issues tokens. The server has no idea how many tokens that have been issued and which tokens that are logged in or not.
So no you can't logout the user, unless you keep some form of state of the issued tokens on the server side, as in storing the tokens in a database and invalidating them when someone does a logout.
And ofc deleting the sessionid cookie wont do anything since you are not using session cookies.
This is the exact reason why you shouldn't be using JWTs as session replacements.
Stop using JWT for sessions, part 2