Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security: CookieTheftException with PersistentTokenBasedRememberMeServices

I have a web application with spring-boot 2.0.1 protected by spring-security. I use a PersistentTokenRepository for Remember-Me and store the tokens in a MySQL database.

In the server logfiles I see quite a lot of stacktraces with CookieTheftExceptions. It's so many that I find it hard to believe that actual Cookies are stolen but assume some kind of misconfiguration. From adding some analyzing code, it seems only mobile browsers are affected.

Servlet.service() for servlet [dispatcherServlet] in context with path [/r] threw exception
  org.springframework.security.web.authentication.rememberme.CookieTheftException: Invalid remember-me token (Series/token) mismatch. Implies previous cookie theft attack.
    at org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices.processAutoLoginCookie(PersistentTokenBasedRememberMeServices.java:119) ~[spring-security-web-5.0.4.RELEASE.jar!/:5.0.4.RELEASE]

Manual testing was not able to reproduce this. Deleting the session cookie, but keeping the remember-me Cookie and making a request to a restricted URL leads to a normal authenticated session.

Here are the relevant parts of my security configuration:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {
    @Configuration
    public static class SecurityConfiguration extends WebSecurityConfigurerAdapter {

        @Autowired
        private RememberMeServices rememberMeServices;

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .rememberMe()
                    .key(rememberMeKey)
                    .rememberMeServices(rememberMeServices);
            ;
        }
    }

    /**
     * Key for RememberMeServices and RememberMeAuthenticationProvider.
     */
    private static final String rememberMeKey = "...";

    @Bean
    public RememberMeServices rememberMeServices(UserDetailsService userDetailsService, PersistentTokenRepository persistentTokenRepository) {
        PersistentTokenBasedRememberMeServices rememberMeServices = new AnalyzingPersistentTokenBasedRememberMeServices(
                rememberMeKey, userDetailsService, persistentTokenRepository);
        rememberMeServices.setTokenValiditySeconds((int) Duration.of(366L, ChronoUnit.DAYS).toSeconds());
        return rememberMeServices;
    }

    @Bean
    public PersistentTokenRepository persistentTokenRepository(JdbcTemplate jdbcTemplate) {
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setJdbcTemplate(jdbcTemplate);
        return tokenRepository;
    }
}

That AnalyzingPersistentTokenBasedRememberMeServices is a PersistentTokenBasedRememberMeServices with some additional logging in processAutoLoginCookie.

Another speciality is, that I use a custom AuthenticationProvider, and provide a UserDetailsService only for RememberMe. But as said above, manual testing works just fine. Still, users report they get logged out too often (session timeout is 24 hours).

Did anybody experience something like this and has a solution? Do I miss some crucial configuration?

like image 459
Rüdiger Schulz Avatar asked Sep 24 '26 03:09

Rüdiger Schulz


1 Answers

PersistentTokenBasedRememberMeServices is not suitable for applications with concurrent requests, which might send the same token series.

See these almost five year old and unresolved bug reports:

https://github.com/spring-projects/spring-security/issues/2648

https://github.com/spring-projects/spring-security/issues/3079

Using TokenBasedRememberMeServices does not have those problems.

like image 105
Rüdiger Schulz Avatar answered Sep 25 '26 16:09

Rüdiger Schulz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!