Expected Behavior

Member authorizationRequestCustomizer of DefaultOAuth2AuthorizationRequestResolver is of type Consumer<OAuth2AuthorizationRequest.Builder>. With changing it to BiConsumer<HttpServletRequest, OAuth2AuthorizationRequest.Builder> we were able to access the request inside the customizer.

Current Behavior

Currently there's no possibility to access the HttpServletRequest inside the authorizationRequestCustomizer.

Context

I would like to add a ui_locales parameter with the value of a query parameter from the request.

Comment From: sjohnr

@dtrunk90 thanks for reaching out.

Spring applications have access to the RequestContextHolder (via RequestContextFilter) which contains ServletRequestAttributes. You can generally access the HttpServletRequest anywhere in the application. I don't think changing the contract of the customizer is required in this case. I'm going to close this issue, but let me know if I have misunderstood anything.

Comment From: dtrunk90

@sjohnr That's one thing I've already tried but I guess at that point the RequestContextFilter wasn't kicked in yet so there are no ServletRequestAttributes (just a guess). This snippet will produce a NullPointerException:

@Configuration
public class OAuth2SecurityConfig {
  @Bean
  public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    return http
            .oauth2Login(oauth2 -> oauth2
                .authorizationEndpoint(authorization -> authorization
                        .authorizationRequestResolver(authorizationRequestResolver))).build();
  }

  @Bean
  public OAuth2AuthorizationRequestResolver authorizationRequestResolver(
      ClientRegistrationRepository clientRegistrationRepository) {
    DefaultOAuth2AuthorizationRequestResolver authorizationRequestResolver =
        new DefaultOAuth2AuthorizationRequestResolver(clientRegistrationRepository,
            OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI);
    authorizationRequestResolver.setAuthorizationRequestCustomizer(customizer ->
        customizer
            .additionalParameters(params -> {
              HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); // java.lang.NullPointerException: Cannot invoke "org.springframework.web.context.request.ServletRequestAttributes.getRequest()" because the return value of "org.springframework.web.context.request.RequestContextHolder.getRequestAttributes()" is null
              params.put("ui_locales", request.getParameter("ui_locales"));
            }));

    return authorizationRequestResolver;
  }
}

Comment From: sjohnr

@dtrunk90 is the above snippet part of a basic Spring Boot application? Or is there any other setup to reproduce? I'm hesitant to consider this a Spring Security issue at the moment as I don't believe we have any control of when the RequestContextHolder is populated. But if the above snippet is enough to reproduce, we can reopen and investigate as I would expect it to work. Perhaps I'm missing something.

Comment From: dtrunk90

@sjohnr Thanks for your answer. I'll try to make a reproducer tomorrow w/ Spring Boot.

Comment From: dtrunk90

Made a reproducer locally with Spring Boot. Turned out it worked so it must be something wrong with my application. I've also tried LocaleContextHolder since I just wanted the Locale. Thanks again.