How to Fix “Exceeded maxRedirects. Probably Stuck in a Redirect Loop” in Spring Security

When developing secure web applications with Spring Security, one of the most frustrating issues developers encounter is the following error:

Exceeded maxRedirects. Probably stuck in a redirect loop

This error typically indicates that the application is continuously redirecting a request between two or more URLs, eventually exceeding the maximum number of allowed redirects. In most cases, the root cause is an incorrect Spring Security configuration, improperly secured endpoints, or authentication logic that redirects users back to protected resources.

This guide explains the common causes of redirect loops in Spring Security and demonstrates how to diagnose and resolve them.


Understanding Redirect Loops

A redirect loop occurs when:

  1. A user requests a protected page.
  2. Spring Security redirects the user to a login page.
  3. The login page itself requires authentication.
  4. Spring Security redirects again to the login page.
  5. The cycle repeats indefinitely.

Example flow:

/test/2
   ↓
/login
   ↓
/login
   ↓
/login
   ↓
Exceeded maxRedirects

Common Cause #1: Login Page Is Protected

One of the most frequent mistakes is securing the login page itself.

Incorrect Configuration

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(auth -> auth
            .anyRequest().authenticated()
        )
        .formLogin(form -> form
            .loginPage("/login")
        );

    return http.build();
}

In this configuration:

  • /login requires authentication.
  • Spring Security redirects unauthenticated users to /login.
  • /login itself requires authentication.
  • Infinite redirect loop occurs.

Correct Configuration

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(auth -> auth
            .requestMatchers("/login").permitAll()
            .anyRequest().authenticated()
        )
        .formLogin(form -> form
            .loginPage("/login")
        );

    return http.build();
}

Now anyone can access the login page.


Common Cause #2: Public Endpoints Not Properly Whitelisted

Suppose the requirement is:

  • /test/1 → Public
  • /test/2 → Authenticated

Correct Security Configuration

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

    http
        .authorizeHttpRequests(auth -> auth
            .requestMatchers("/test/1").permitAll()
            .requestMatchers("/test/2").authenticated()
            .anyRequest().authenticated()
        )
        .formLogin(Customizer.withDefaults());

    return http.build();
}

If /test/1 is accidentally omitted from permitAll(), requests may be redirected unexpectedly.


Common Cause #3: Incorrect Success or Failure URLs

Authentication success and failure handlers can create loops.

Problematic Example

.formLogin(form -> form
    .defaultSuccessUrl("/login")
)

After successful login:

/login
 ↓
authenticate
 ↓
/login
 ↓
authenticate
 ↓
loop

Correct Example

.formLogin(form -> form
    .defaultSuccessUrl("/dashboard", true)
)

Common Cause #4: Reverse Proxy Configuration

Applications behind:

  • Nginx
  • Apache
  • Load Balancers
  • Kubernetes Ingress

may encounter redirect loops due to HTTP/HTTPS mismatches.

Example

Browser:

https://example.com

Proxy forwards:

http://localhost:8080

Spring thinks the request is HTTP and redirects:

https://example.com/login

The proxy forwards again, creating a loop.

Solution

Enable forwarded headers:

server.forward-headers-strategy=framework

Or:

@Bean
ForwardedHeaderFilter forwardedHeaderFilter() {
    return new ForwardedHeaderFilter();
}

Common Cause #5: Session Problems

If the session cannot be created or maintained:

  1. User logs in successfully.
  2. Session cookie is lost.
  3. Next request appears unauthenticated.
  4. User is redirected to login again.

Potential causes include:

  • Invalid cookie settings
  • Domain mismatch
  • Secure cookie issues
  • Browser blocking cookies

Check browser developer tools:

Application → Cookies

Verify that:

  • Session cookie exists
  • Cookie domain is correct
  • Cookie path is correct

Common Cause #6: Custom Security Filters

Custom filters may accidentally trigger redirects.

Example:

if(authentication == null) {
    response.sendRedirect("/login");
}

If the filter executes on /login itself:

/login
 ↓
custom filter
 ↓
/login
 ↓
custom filter
 ↓
loop

Always exclude authentication pages from custom redirect logic.

Example:

if(request.getRequestURI().equals("/login")) {
    filterChain.doFilter(request, response);
    return;
}

How to Diagnose Redirect Loops

Enable Spring Security Debug Logging

logging.level.org.springframework.security=DEBUG

Or:

@EnableWebSecurity(debug = true)

This produces detailed logs showing:

Securing GET /test/2
Redirecting to /login
Securing GET /login
Redirecting to /login

The repeated pattern quickly reveals the source of the loop.


Test with cURL

Inspect redirect behavior directly:

curl -I http://localhost:8080/test/2

Follow redirects:

curl -L http://localhost:8080/test/2

Or show each redirect step:

curl -v http://localhost:8080/test/2

Look for repeated Location headers.


Complete Example

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http)
            throws Exception {

        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/test/1").permitAll()
                .requestMatchers("/login").permitAll()
                .requestMatchers("/test/2").authenticated()
                .anyRequest().authenticated()
            )
            .formLogin(Customizer.withDefaults());

        return http.build();
    }
}

Behavior:

EndpointAuthentication Required
/test/1No
/loginNo
/test/2Yes
Other endpointsYes

Best Practices

  • Always whitelist login and logout endpoints.
  • Explicitly define public resources.
  • Verify success and failure redirect URLs.
  • Enable Spring Security debug logging during troubleshooting.
  • Validate session cookie behavior.
  • Carefully review custom filters and interceptors.
  • Verify proxy and HTTPS forwarding configuration.

Conclusion

The “Exceeded maxRedirects. Probably stuck in a redirect loop” error is usually caused by a misconfiguration in Spring Security, authentication flows, session handling, or reverse proxy setups. By carefully reviewing endpoint permissions, login page accessibility, redirect targets, and session behavior, developers can quickly identify and eliminate redirect loops.

A well-structured Spring Security configuration should clearly separate public and protected endpoints, ensure login pages remain accessible, and avoid circular redirect paths that trap users in endless authentication cycles.

 

This article is inspired by real-world challenges we tackle in our projects. If you're looking for expert solutions or need a team to bring your idea to life,

Let's talk!

    Please fill your details, and we will contact you back

      Please fill your details, and we will contact you back