javaspring-bootspring-securityopenid-connectopenid

Redirect Loop Issue with OpenID Authentication in Spring Boot 3.3


I'm working on a REST API using Java 21 with Spring Boot 3.3, and I'm trying to implement authentication through an external site using OpenID. However, I'm encountering a redirect loop after logging in on the external site.

Here’s a brief overview of the flow:

1- I navigate to localhost:41448/schedule/{id}.

2- I'm redirected to myExternalWebsite.com and successfully log in with my credentials. This part works fine!

3- The POST on my token-uri with good body is OK and return a Response 200 OK

4- I'm redirected to my redirect URL (localhost:41448/redirect-uri), but it seems my controller is never reached. Instead, I see multiple redirects in the network tab. I have this error: ERR_TOO_MANY_REDIRECTS

I’ve been struggling with this for the past week, getting lost in a lot of documentation (some of it outdated).

If you need any more information or details, please don’t hesitate to ask!

Thank you in advance for your help!

Here’s my application.yml configuration:

security:
  oauth2:
    client:
      registration:
        esante:
          client-id: MyId
          client-secret: MyClientSecret
          scope: openid
          redirect-uri: "https://localhost:41448/redirect-uri"
          authorization-grant-type: authorization_code
          client-name: example
      provider:
        example:
          authorization-uri: https://myExternalWebsite.integration.fr/realms/sas/protocol/openid-connect/auth
          token-uri: https://myExternalWebsite.integration.fr/realms/sas/protocol/openid-connect/token
          user-info-uri: https://myExternalWebsite.integration.fr/realms/sas/protocol/openid-connect/userinfo
          issuer-uri: https://myExternalWebsite.integration.fr/realms/sas

And here’s my security configuration:

@EnableWebSecurity
public class SecurityConfig {

  @Bean
  public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http.authorizeHttpRequests(
            authorizeRequests ->
                authorizeRequests
                    .requestMatchers("/redirect-uri")
                    .permitAll()
                    .anyRequest()
                    .authenticated()
            )
        .oauth2Login(
            oauth2Login ->
                oauth2Login
                    .loginPage("https://myExternalWebsite.integration.fr") // OAuth2 login page
                    .defaultSuccessUrl("/redirect-uri", true) // Redirect after login
            )
        .requiresChannel(
            channel ->
                channel.anyRequest().requiresSecure()
            );

    return http.build();
  }
}

Here is my trace (this log repeats many times):

HTTP POST https://myExternalWebsite.integration.fr/realms/sas/protocol/openid-connect/token
Accept=[application/json, application/*+json]
Writing [{grant_type=[authorization_code], code=[{code_generate}], redirect_uri=[https://localhost:41448/redirect-uri]}] as "application/x-www-form-urlencoded;charset=UTF-8"
Response 200 OK
Reading to [org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse] as "application/json"
HTTP POST https://myExternalWebsite.integration.fr/realms/sas/protocol/openid-connect/token
Accept=[application/json, application/*+json]
Writing [{grant_type=[authorization_code], code=[{code_generate}], redirect_uri=[https://localhost:41448/redirect-uri]}] as "application/x-www-form-urlencoded;charset=UTF-8"
Response 200 OK
Reading to [org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse] as "application/json"

Solution

  • My problem was in SecurityConfiguration and redirect-uri.

    It's big mistake to link redirect-uri to my own rest controller, so now my redirect-uri is {baseUrl}/login/oauth2/code/{registrationId}

    And for SecurityConfig

    @Bean
      public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeRequests(
                authorizeRequests ->
                    authorizeRequests.antMatchers("/").permitAll().anyRequest().authenticated())
            .oauth2Login(
                oauth2Login ->
                    oauth2Login
                        .loginPage("https://myExternalWebsite.integration.fr")
                        .successHandler(customAuthenticationSuccessHandler())
                        .failureHandler(customAuthenticationFailureHandler())
                );
        return http.build();
      }