Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security OAuth2 Redirect Loop

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

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 SecurityContextPersistenceFilter the contextBeforeChainExecution and contextAfterChainExecution both have a null authentication.

I have based some of the code on [1]Spring Security OAuth2 (google) web app in redirect loop

Any ideas as to why the redirect loop? Thank you in advance.

[Logs snippet]https://gist.github.com/yterradas/61da3f6eccc683b3a086

Below is the config for security.

@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;
    }

  }
}
like image 684
Yoandy Terradas Avatar asked Nov 14 '14 20:11

Yoandy Terradas


1 Answers

I think you have 2 OAuth2ClientContextFilters (one is added by @EnableOAuth2Client and you have added another manually to the Spring Security filter chain). You should be able to remove the one you added.

like image 68
Dave Syer Avatar answered Sep 29 '22 00:09

Dave Syer