Skip to content

Improve documentation for configuring Spring Security with '/error' #45663

Closed
@UsamaButt1593

Description

@UsamaButt1593

When using Spring Boot with Spring Security, if an unauthenticated user sends a request to a public endpoint e.g. /auth/signup that results in an exception (e.g., validation error), Spring framework intercepts the error and redirects it to the /error endpoint.

By default, Spring Boot configures /error for exception resolution. However, Spring Security also protects /error, requiring authentication by default.

As a result, expected application exceptions (like MethodArgumentNotValidException) are never properly returned to the client for unauthenticated users. Instead, the user receives a 403 Forbidden or 401 Unauthorized error, and the original exception details are lost.

This breaks consistent error handling for APIs that are supposed to be public (e.g., /auth/signup).

Environment

  • Spring Boot version: 3.2.x
  • Spring Security version: 6.x
  • Java: 17+
  • Application Type: REST API using stateless authentication (JWT)

Code to reproduce

// Controller
@RestController
@RequestMapping("/auth")
public class AuthController {
    
    @Autowired
    private AuthService authService;

    @PostMapping("/signup")
    public ResponseEntity<?> signUp(@Valid @RequestBody SignUpRequestDTO signUpRequestDTO) {
        return ResponseEntity.ok(
            userService.createUser(signUpRequestDTO.getEmail(), signUpRequestDTO.getPassword())
         );
    }


// DTO
@Data
public class CreateUserRequestDTO {
    @Email
    private String email;

    @NotBlank
    private String password;
}

// Config
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {

        @Bean
        public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
                return http.csrf(csrf -> csrf.disable())
                                .authorizeHttpRequests(auth -> auth
                                    .requestMatchers("/auth/**").permitAll()
                                    .anyRequest().authenticated())
                                .build();
        }

}

}

if we send a http request with invalid body like:

POST http://localhost:8080/auth/signup
Content-Type: application/json

{
  "email": "NOT_A_VALID_EMAIL",
  "password": "password"
}

expected response should be 400 Bad Request with error details while actual response we get is 401 Unauthorized.

HTTP/1.1 401 
X-Content-Type-Options: nosniff
X-XSS-Protection: 0
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: application/json
Content-Length: 121
Connection: close

{
  "path": "/error",
  "error": "Unauthorized",
  "message": "Full authentication is required to access this resource",
  "status": 401
}

Expected Behavior

The /error endpoint should either:

  • Be permitted by default in Spring Security to allow unauthenticated users to receive meaningful error responses, or
  • The documentation should clearly recommend developers permit the /error endpoint in security configuration when using stateless APIs.

Additional Context

This behavior is confusing and non-obvious to developers building public or semi-public REST APIs. Better defaults or clearer documentation would significantly improve the developer experience.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions