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;
}
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With