title: Spring remember-me with extra login parameter
body: <p>In a spring mvc application i am capturing an additional 'location' parameter on login screen and using it for authentication in addition to username. So in 'loadUserByUsername' my sql query is something like,</p>
  
  <pre><code>select from user where username = ? and location = ? 
  </code></pre>
  
  <p>Now, if user is a remember-me user then there is no way to capture 'location' parameter because there won't be a login prompt. In case of remember-me feature spring stores only username in cookie. And for remember-me login it then retrieves that username from cookie and passes it to 'loadUserByUsername' call to load user from DB. So, in my case, for remember-me users, since 'location' is null query to load user fails.<br> 
  I wanted to know if there is a way to override the default spring behavior and store 'location' in cookie along with username and then pass location and username to 'loadUserByUsername' in PersistentTokenBasedRememberMeServices.processAutoLoginCookie().<br>
  Please see my code below for reference,</p>
  
  <p>CustomAuthenticationFilter.java :-</p>
  
  <pre><code>public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
  
      @Override
      public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
          final Long locationId = Long.parseLong(request.getParameter("locations"));
          request.getSession().setAttribute("LOCATION_ID", locationId);
  
          return super.attemptAuthentication(request, response); 
      } 
  }
  </code></pre>
  
  <p>SecurityConfig.java:-</p>
  
  <pre><code>public class SecurityConfig extends WebSecurityConfigurerAdapter {
  
      @Autowired
      DataSource dataSource;
  
      @Autowired
      private AuthenticationManagerBuilder auth;
  
      @Autowired
      public void configureGlobal(UserDetailsService userDetailsService, AuthenticationManagerBuilder auth) throws Exception {
          auth
          .userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
      }
  
      @Bean
      public PasswordEncoder passwordEncoder() {
          return new BCryptPasswordEncoder();
      }
  
      @Autowired
      AccessDeniedExceptionHandler accessDeniedExceptionHandler;
  
      @Bean
      public CustomInvalidSessionStrategy invalidSessionStrategy() {
          return new CustomInvalidSessionStrategy();
      }
  
      @Override
      protected void configure(HttpSecurity http) throws Exception {
          http
          .authorizeRequests()
          .antMatchers("/resources/**").permitAll()
          .antMatchers("/error/**").permitAll()
          .antMatchers("/secured/**").hasRole("ADMIN")
          .anyRequest().authenticated()
          .and()
          .formLogin()
          .loginPage("/login")
  //      .defaultSuccessUrl("/")
          .permitAll()
          .and().rememberMe().rememberMeServices(persistentTokenBasedRememberMeServices())
          .and()
          .logout()
          .permitAll()
          .and()
          .exceptionHandling()
          .accessDeniedHandler(accessDeniedExceptionHandler);
  
          http.addFilterBefore(customAuthenticationFilter(),
                  UsernamePasswordAuthenticationFilter.class);
          http.addFilterAfter(rememberMeAuthenticationFilter(),
                  UsernamePasswordAuthenticationFilter.class);
      }
  
      @Bean
      @Override
      public AuthenticationManager authenticationManagerBean() {
          AuthenticationManager manager = null;
          try {
              manager = super.authenticationManagerBean();
          } catch (Exception e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }
          return manager;
      }
  
  
      @Bean
      public SimpleUrlAuthenticationSuccessHandler simpleUrlAuthenticationSuccessHandler() {
          SimpleUrlAuthenticationSuccessHandler handler = new SimpleUrlAuthenticationSuccessHandler();
          handler.setDefaultTargetUrl("/");
          return handler;
      }
  
      @Bean
      public SimpleUrlAuthenticationFailureHandler simpleUrlAuthenticationFailureHandler() {
          SimpleUrlAuthenticationFailureHandler handler = new SimpleUrlAuthenticationFailureHandler();
          handler.setDefaultFailureUrl("/login?error");
          return handler;
      }
  
      @Bean
      public CustomAuthenticationFilter customAuthenticationFilter () {
          CustomAuthenticationFilter filter= new  CustomAuthenticationFilter();
          filter.setRequiresAuthenticationRequestMatcher(
                  new AntPathRequestMatcher("/login","POST"));
          filter.setAuthenticationManager(authenticationManagerBean());
          filter.setUsernameParameter("username");
          filter.setPasswordParameter("password");
          filter.setAuthenticationSuccessHandler(simpleUrlAuthenticationSuccessHandler());
          filter.setAuthenticationFailureHandler(simpleUrlAuthenticationFailureHandler());
          filter.setRememberMeServices(persistentTokenBasedRememberMeServices());
          return filter;
      }
  
      @Bean
      public RememberMeAuthenticationFilter rememberMeAuthenticationFilter() {
          RememberMeAuthenticationFilter filter = new RememberMeAuthenticationFilter();
          filter.setAuthenticationManager(authenticationManagerBean());
          filter.setRememberMeServices(persistentTokenBasedRememberMeServices());
          return filter;
      }
  
      @Bean
      public PersistentTokenBasedRememberMeServices persistentTokenBasedRememberMeServices() {
          PersistentTokenBasedRememberMeServices service = new PersistentTokenBasedRememberMeServices("remember_me_key", userDetailsService, persistentTokenRepository());
          service.setCookieName("remember_me");
          service.setTokenValiditySeconds(864000);
          return service;
      }
  
      @Autowired
      public UserDetailsService userDetailsService;
  
      @Bean
      public PersistentTokenRepository persistentTokenRepository() {
          JdbcTokenRepositoryImpl tokenRepositoryImpl = new JdbcTokenRepositoryImpl();
          tokenRepositoryImpl.setDataSource(dataSource);
          return tokenRepositoryImpl;
      }
  }
  </code></pre>