Troubleshooting Spring Security CORS Issues, Deprecated Configuration, and Forbidden Login Endpoints

Introduction

A common challenge when developing modern web applications is connecting an Angular frontend running on one origin to a Spring Boot backend running on another. Developers frequently encounter errors such as:

Cross-Origin Request Blocked:
The Same Origin Policy disallows reading the remote resource.
Reason: CORS header 'Access-Control-Allow-Origin' missing.
Status code: 403

After attempting to enable CORS, additional issues often appear:

  • IllegalArgumentException related to allowedOrigins
  • Deprecated Spring Security methods
  • HTTP 403 Forbidden responses
  • Authentication entry point errors

This guide explains the most common causes and solutions.


Understanding the CORS Problem

Suppose your Angular application is running on:

http://localhost:4200

and your Spring Boot backend is running on:

http://192.168.50.151:8080

When Angular attempts to call:

POST /login

the browser sends a CORS preflight request before the actual login request.

If the backend does not explicitly allow the frontend origin, the browser blocks the request.


Common Incorrect Configuration

Many developers initially try:

CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");

This causes the following exception:

IllegalArgumentException:
When allowCredentials is true,
allowedOrigins cannot contain "*"

Why This Happens

When credentials are enabled:

config.setAllowCredentials(true);

the server must return a specific origin:

Access-Control-Allow-Origin: http://localhost:4200

Returning:

Access-Control-Allow-Origin: *

is not permitted by the CORS specification.


Correct Solution Using allowedOriginPatterns

Instead of:

config.addAllowedOrigin("*");

use:

config.addAllowedOriginPattern("*");

Example:

@Bean
public CorsConfigurationSource corsConfigurationSource() {

    CorsConfiguration configuration = new CorsConfiguration();

    configuration.setAllowCredentials(true);
    configuration.addAllowedOriginPattern("*");
    configuration.addAllowedHeader("*");
    configuration.addAllowedMethod("*");

    UrlBasedCorsConfigurationSource source =
            new UrlBasedCorsConfigurationSource();

    source.registerCorsConfiguration("/**", configuration);

    return source;
}

Spring Security 6 Configuration

Recent versions of Spring Security no longer use:

WebSecurityConfigurerAdapter

and many methods have been deprecated.

Instead, configure security using:

SecurityFilterChain

Example:

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

    http
        .csrf(csrf -> csrf.disable())
        .cors(withDefaults())
        .authorizeHttpRequests(auth -> auth
            .requestMatchers("/login").permitAll()
            .anyRequest().authenticated()
        );

    return http.build();
}

Deprecated httpBasic() Method

Older configurations used:

http.httpBasic();

Modern Spring Security recommends:

http.httpBasic(withDefaults());

Example:

import static org.springframework.security.config.Customizer.withDefaults;

http.httpBasic(withDefaults());

Handling Preflight OPTIONS Requests

A very common reason for receiving:

403 Forbidden

is that Spring Security blocks the browser’s preflight request.

Browsers automatically send:

OPTIONS /login

before:

POST /login

You must allow these requests.

Example:

.authorizeHttpRequests(auth -> auth
    .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
    .requestMatchers("/login").permitAll()
    .anyRequest().authenticated()
)

Why “Forbidden Entry Point” Happens

If Spring Security receives an unauthenticated request and does not know how to handle it, it may trigger an authentication entry point and return:

403 Forbidden

or

401 Unauthorized

Typical causes include:

  • Missing permitAll() on /login
  • Blocked OPTIONS requests
  • Custom authentication filters intercepting login requests
  • Incorrect filter ordering

Recommended Security Configuration

A simplified modern configuration:

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

    http
        .csrf(csrf -> csrf.disable())
        .cors(withDefaults())
        .authorizeHttpRequests(auth -> auth
            .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
            .requestMatchers("/login").permitAll()
            .anyRequest().authenticated()
        );

    return http.build();
}

CORS configuration:

@Bean
public CorsConfigurationSource corsConfigurationSource() {

    CorsConfiguration config = new CorsConfiguration();

    config.setAllowCredentials(true);
    config.addAllowedOriginPattern("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");

    UrlBasedCorsConfigurationSource source =
            new UrlBasedCorsConfigurationSource();

    source.registerCorsConfiguration("/**", config);

    return source;
}

Angular Client Example

Angular login request:

this.http.post(
  'http://192.168.50.151:8080/login',
  credentials,
  {
    withCredentials: true
  }
);

If credentials such as cookies or sessions are used, the withCredentials flag must match the server’s CORS configuration.


Debugging Tips

When troubleshooting CORS and authentication issues:

Check Browser Developer Tools

Look for:

OPTIONS /login

and verify the response headers.

Verify Access-Control Headers

The response should contain:

Access-Control-Allow-Origin
Access-Control-Allow-Headers
Access-Control-Allow-Methods

Enable Spring Security Debug Logging

logging.level.org.springframework.security=DEBUG

This reveals which filter rejects the request.

Test With curl

Example:

curl -X OPTIONS \
  http://192.168.50.151:8080/login \
  -H "Origin: http://localhost:4200" \
  -H "Access-Control-Request-Method: POST"

This helps determine whether the issue is CORS-related or authentication-related.


Conclusion

When integrating Angular with Spring Boot, CORS and security configuration issues are among the most common causes of failed login requests. Modern Spring Security requires updated configuration patterns using SecurityFilterChain, proper CORS handling with allowedOriginPatterns, and explicit permission for preflight OPTIONS requests.

By correctly configuring CORS, updating deprecated APIs, and allowing unauthenticated access to login endpoints, frontend applications can securely communicate with backend services without encountering browser-side CORS errors or Spring Security authorization failures.

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