Describe the bug The default autoconfiguration of OAuth2 client:
@Bean
SecurityFilterChain oauth2SecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests((requests) -> requests.anyRequest().authenticated());
http.oauth2Login(Customizer.withDefaults()); // <----------------
http.oauth2Client(); // <--------------------------------------------
return http.build();
}
end up registering the OAuth2AuthorizationRequestRedirectFilter twice. If I dump the filter chain I see:
any request
org.springframework.security.web.session.DisableEncodeUrlFilter@7fad214a
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@164642a4
org.springframework.security.web.context.SecurityContextHolderFilter@51bddd98
org.springframework.security.web.header.HeaderWriterFilter@4faf104
org.springframework.security.web.csrf.CsrfFilter@671ea6ff
org.springframework.security.web.authentication.logout.LogoutFilter@2e43c38d
-> org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter@104dc1a2 <-
-> org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter@314a31b0 <-
org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter@67d32a54
org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@235b4cb8
org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter@75cf0de5
org.springframework.security.web.savedrequest.RequestCacheAwareFilter@77d4ac52
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@252744a1
org.springframework.security.web.authentication.AnonymousAuthenticationFilter@50b0afd7
org.springframework.security.oauth2.client.web.OAuth2AuthorizationCodeGrantFilter@4735d6e5
org.springframework.security.web.access.ExceptionTranslationFilter@49fb0bbd
org.springframework.security.web.access.intercept.AuthorizationFilter@24c8d8be
BTW this was reported originally against Springboot here: https://github.com/spring-projects/spring-boot/issues/34406
This is confusing as the breakpoint hits twice if the request is going past these filters. If the first filter handles the request then second instance is never called.
To Reproduce Use the default OAuth2 client autoconfiguration and look at the filters in the filter chain.
Expected behavior
The both oauth2Login() and oauth2Client() DSLs are used just install the OAuth2AuthorizationRequestRedirectFilter filter only once.
Sample N/A
Comment From: marcusdacoregio
Hi @sandipchitale.
I believe that this behavior is expected since both oauth2Login() and oauth2Client() configures the authorization_code slightly different, oauth2Login() assumes a redirect uri of {baseUrl}/login/oauth2/code/{registrationId} and uses a RequestCache to replay the request prior to authentication. While oauth2Client() uses any redirect uri you want and continues the filter chain afterward. But that could be wrong.
With that said, does having those two filters cause you any problems?
Comment From: sandipchitale
@marcusdacoregio I understand that oauth2Login() and oauth2Client() handle different things. Even though having the same filter ( OAuth2AuthorizationRequestRedirectFilter ) in filter chain does not cause a functional problem but it was very confusing when I had set a breakpoint in the filter and it was getting hit twice. It took me some time to realize that two instances of the same filter were in the chain (when I looked at the @nnnn object id in the debugger variables view). Because both the DSLs come from the same library, I was suggesting if the two DSLs could coordinate and use the same filter instance.
Also note that when request qualifies to be handled by the filter the first one processes it and second one is not used. When the request does not qualify it just passes past both instances, meaning only one instance is really used when applicable.
Comment From: sandipchitale
BTW the same issue was filed again Springboot https://github.com/spring-projects/spring-boot/issues/34406 . I was requested to file it here.
Comment From: sjohnr
@sandipchitale I'm sorry you ran into confusion with two instances of the filter in the filter chain. This issue is a side-effect of a design decision that is probably a bit beyond changing at this point. The DSL for oauth2Login() vs oauth2Client() do allow configuring things differently as @marcusdacoregio mentioned. Because of that, it would not be simple to combine the two cases without breaking backwards compatibility.
However, I will mention that as we look towards Spring Security 7, we are thinking a lot about these types of issues and aiming to simplify configuration and make it less confusing in general, so this is extremely valuable feedback.
Having said that, I'm going to close this issue for now. If you do find a functional issue, let us know and we can re-open to look deeper.
Comment From: sandipchitale
Glad to hear you are thinking of simplifying this. Great work BTW. Thanks you. I filed the issue here as well so that you are aware people are raising similar issues on Springboot.