javaspringspring-mvcspring-security

Replacing default RememberMeAuthenticationProvider added by spring-security


I need to provide my own custom RememberMeAuthenticationProvider provider, which I know how to do. But the default created one is still present in the ProviderManager list of providers.

Can I completely replace the default one with my custom one?

How I add my own

    @Bean
    public RememberMeAuthenticationProvider rememberMeAuthenticationProvider(MessageSource messageSource) {
        var authProvider = new MyRememberMeAuthenticationProvider(REMEMBER_ME_KEY);
        authProvider.setMessageSource(messageSource);
        return authProvider;
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http,
                                           MvcRequestMatcher.Builder mvc,
                                           MessageSource messageSource) throws Exception {
        http
                .csrf(csrf -> csrf.csrfTokenRequestHandler(csrfRequestHandler)
                        .ignoringRequestMatchers(LOGIN_URI + "**"))
                .authenticationProvider(authenticationProvider)
                .authenticationProvider(rememberMeAuthenticationProvider(messageSource))
<cut>
        return http.build();
    }

But the RememberMeConfigurer unconditionally adds the default one

@Override
public void configure(H http) {
    RememberMeAuthenticationFilter rememberMeFilter = new RememberMeAuthenticationFilter(
            http.getSharedObject(AuthenticationManager.class), this.rememberMeServices);
    if (this.authenticationSuccessHandler != null) {
        rememberMeFilter.setAuthenticationSuccessHandler(this.authenticationSuccessHandler);
    }
    SecurityContextConfigurer<?> securityContextConfigurer = http.getConfigurer(SecurityContextConfigurer.class);
    if (securityContextConfigurer != null && securityContextConfigurer.isRequireExplicitSave()) {
        SecurityContextRepository securityContextRepository = securityContextConfigurer
            .getSecurityContextRepository();
        rememberMeFilter.setSecurityContextRepository(securityContextRepository);
    }
    rememberMeFilter.setSecurityContextHolderStrategy(getSecurityContextHolderStrategy());
    rememberMeFilter = postProcess(rememberMeFilter);
    http.addFilter(rememberMeFilter);
}

Which leads to this list of configured providers

0 = {MyAuthenticationProvider@17013} 
1 = {MyRememberMeAuthenticationProvider@16992} 
2 = {AnonymousAuthenticationProvider@26592} 
3 = {RememberMeAuthenticationProvider@18312} 

Right now this works, likely due to the order, but I would really want to remove the default one completely.

Is this possible?

Many thanks, Mike


Solution

  • I think you can use BeanPostProcessor like so

    public class MyBeanPostProcessor implements BeanPostProcessor {
    
     @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if (bean instanceof ProviderManager providerManager) {
                providerManager.getProviders().removeIf(provider -> provider.getClass() == RememberMeAuthenticationProvider.class);
            }
            return bean;
        }
    
    }