title: Spring Security OAuth2 Redirect Loop
body: <p>I have a oauth2 client spring-boot application with dependencies: 
   - spring-boot 1.2.0.RC1
   - spring-security-oauth2 2.0.4.RELEASE
   - spring-security 3.2.5.RELEASE</p>
  
  <p>The client authenticates, the authentication is set in the SecurityContextHolder but when the request is redirected to the original url the filter chain starts processing again.  I noticed that in the <code>SecurityContextPersistenceFilter</code> the contextBeforeChainExecution and contextAfterChainExecution both have a null authentication.  </p>
  
  <p>I have based some of the code on [1]<a href="https://stackoverflow.com/questions/26056780/spring-security-oauth2-google-web-app-in-redirect-loop">Spring Security OAuth2 (google) web app in redirect loop</a></p>
  
  <p>Any ideas as to why the redirect loop?  Thank you in advance.  </p>
  
  <p>[Logs snippet]<a href="https://gist.github.com/yterradas/61da3f6eccc683b3a086" rel="noreferrer">https://gist.github.com/yterradas/61da3f6eccc683b3a086</a></p>
  
  <p>Below is the config for security.  </p>
  
  <pre>@Configuration
  public class SecurityConfig {
  
    @Configuration
    @EnableWebMvcSecurity
    protected static class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  
      @Autowired
      private OAuth2ClientAuthenticationProcessingFilter oAuth2ClientAuthenticationProcessingFilter;
  
      @Autowired
      private LoginUrlAuthenticationEntryPoint vaultAuthenticationEntryPoint;
  
      @SuppressWarnings({"SpringJavaAutowiringInspection"})
      @Autowired
      private OAuth2ClientContextFilter oAuth2ClientContextFilter;
  
      @Override
      protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http
            .authorizeRequests()
              .antMatchers("/**").authenticated()
          .and()
            .exceptionHandling().authenticationEntryPoint(vaultAuthenticationEntryPoint)
          .and()
            .addFilterAfter(oAuth2ClientContextFilter, ExceptionTranslationFilter.class)
            .addFilterBefore(oAuth2ClientAuthenticationProcessingFilter, FilterSecurityInterceptor.class)
            .anonymous().disable();
      // @formatter:on
      }
  
      @Override
      public void configure(WebSecurity web) throws Exception {
        // @formatter:off
      web
         /* TODO:
         disable debug in production
         */
         .debug(true);
      // @formatter:on
      }
    }
  
    @Configuration
    @EnableOAuth2Client
    protected static class ClientSecurityConfig {
  
      @Value("${app.name}") private String appId;
      @Value("${app.clientId}") private String appClientId;
      @Value("${app.clientSecret}") private String appClientSecret;
      @Value("${app.redirectUrl}") private String appRedirectUrl;
      @Value("${vault.accessTokenUrl}") private String vaultAccessTokenUrl;
      @Value("${vault.userAuthorizationUrl}") private String vaultUserAuthorizationUrl;
      @Value("${vault.checkTokenUrl}") private String vaultCheckTokenUrl;
  
      @SuppressWarnings({"SpringJavaAutowiringInspection"})
      @Resource
      @Qualifier("oauth2ClientContext")
      private OAuth2ClientContext oAuth2ClientContext;
  
      @Autowired
      @Qualifier("securityDataSource")
      private DataSource securityDataSource;
  
      @Autowired
      private MappingJackson2HttpMessageConverter jackson2HttpMessageConverter;
  
      @Bean
      public OAuth2RestOperations oAuth2RestOperations() {
        AccessTokenProviderChain provider = new AccessTokenProviderChain(
            Arrays.asList(new AuthorizationCodeAccessTokenProvider())
        );
        provider.setClientTokenServices(new JdbcClientTokenServices(securityDataSource));
  
        OAuth2RestTemplate template = new OAuth2RestTemplate(oAuth2Resource(), oAuth2ClientContext);
        template.setAccessTokenProvider(provider);
        template.setMessageConverters(Arrays.asList(jackson2HttpMessageConverter));
  
        return template;
      }
  
      @Bean
      OAuth2ProtectedResourceDetails oAuth2Resource() {
        AuthorizationCodeResourceDetails resource = new AuthorizationCodeResourceDetails();
  
        resource.setId(appId);
        resource.setAuthenticationScheme(AuthenticationScheme.query);
        resource.setAccessTokenUri(vaultAccessTokenUrl);
        resource.setUserAuthorizationUri(vaultUserAuthorizationUrl);
        resource.setUseCurrentUri(false);
        resource.setPreEstablishedRedirectUri(appRedirectUrl);
        resource.setClientId(appClientId);
        resource.setClientSecret(appClientSecret);
        resource.setClientAuthenticationScheme(AuthenticationScheme.form);
  
        return resource;
      }
  
      @Bean
      ResourceServerTokenServices oAuth2RemoteTokenServices() {
        VaultTokenServices tokenServices = new VaultTokenServices();
  
        RestTemplate restOperations = new RestTemplate();
        restOperations.setMessageConverters(Arrays.asList(jackson2HttpMessageConverter));
  
        tokenServices.setRestTemplate(restOperations);
        tokenServices.setClientId(appClientId);
        tokenServices.setClientSecret(appClientSecret);
        tokenServices.setCheckTokenEndpointUrl(vaultCheckTokenUrl);
  
        return tokenServices;
      }
  
      @Bean
      LoginUrlAuthenticationEntryPoint oAuth2AuthenticationEntryPoint() {
        return new LoginUrlAuthenticationEntryPoint("/vaultLogin");
      }
  
      @Bean
      OAuth2ClientAuthenticationProcessingFilter oAuth2ClientAuthenticationProcessingFilter() {
        OAuth2ClientAuthenticationProcessingFilter filter =
            new OAuth2ClientAuthenticationProcessingFilter("/vaultLogin");
  
        filter.setRestTemplate(oAuth2RestOperations());
        filter.setTokenServices(oAuth2RemoteTokenServices());
  
        return filter;
      }
  
    }
  }</pre>