Spring Security OAuth2 Redirect Loop

I have a spring-boot oauth2 client 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 to the SecurityContextHolder, but when the request is redirected to the original URL, the filter chain starts processing again. I noticed that in SecurityContextPersistenceFilter

contextBeforeChainExecution and contextAfterChainExecution both have null authentication.

I based some code on [1] Spring OAuth2 security web application (google) in a redirect loop

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

[Log snapshots] https://gist.github.com/yterradas/61da3f6eccc683b3a086

Below is the security configuration.

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

  }
}
+5


source to share


3 answers


I think you have 2 OAuth2ClientContextFilters

(one added @EnableOAuth2Client

and you added another key to your Spring filter chain). You can delete the one you added.



+2


source


I found a mediocre solution that entailed removing almost every filter from SecurityFilterChain

. Unfortunately, I don't have a working copy of the application I was working on. However, it should be easy to reproduce the solution by removing as many filters as possible before it breaks the application, then add only the ones you need. If my memory serves me correctly, the culprit was either SecurityContextPersistenceFilter

or RequestCacheAwareFilter

.



0


source


For others who might come here with the same problem - a redirect loop when using Spring Security oAuth. I had this because I am behind a firewall that blocks any direct access to the Internet, and my Spring Boot + Security application needs to call a userinfo IdP endpoint that was located on the Internet, like Okta, Google, etc. You can fix this by setting up a proxy in your local startup configuration like this:

-Dhttp.proxyHost=yourhttpproxy.company.com 
-Dhttp.proxyPort=yourhttproxyport
-Dhttp.nonProxyHosts='localhost|*.yourintranetdomain1.com|*.yourintranetdomain2.com|etc' 
-Dhttps.proxyHost=yourhttpsproxy.company.com
-Dhttps.proxyPort=yourhttpsproxyport 
-Dhttps.nonProxyHosts='localhost|*.yourintranetdomain1.com|*.yourintranetdomain2.com|etc'

      

Hope this helps.

0


source







All Articles