javaspringspring-bootspring-security

Spring Boot @PostMapping Endpoint Not Hit While @GetMapping Works after adding securityFilterChain


I'm learning Spring Boot with Spring Security, and I'm having trouble with a @PostMapping endpoint in my AuthController. The @GetMapping endpoint works fine, but the @PostMapping endpoint is never hit. I've verified the request using Postman, and everything seems correct. Here are the details:

Security Configuration (SecurityConfig):

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
    @Bean
    public UserDetailsService userDetailsService() {
        // Define your custom UserDetailsService implementation
        return new CustomUserDetailsService();
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests(req ->
                        req.requestMatchers(
                                        "/auth/**",
                                        "/css/**.css",
                                        "/js/**"
                                ).permitAll()
                                .anyRequest().authenticated()
                )
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));

        return http.build();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }
}

AuthController:

@RestController
@RequestMapping("/auth")
public class AuthController {
    @GetMapping("/test")
    public String test() {
        return "Testing GET in Auth Ctrl.";
    }

    @PostMapping("/login")
    public String login(@RequestBody AuthRequest authRequest) {
        try {
            if(authRequest.getUsername() == null || authRequest.getPassword() == null)
                throw new AuthenticationException("AuthRequest is empty");

            // Assuming successful authentication, you would normally return a JWT token here
            return "Login successful!";
        } catch (AuthenticationException e) {
            return "Login failed!";
        }
    }
}

@Data
@NoArgsConstructor
class AuthRequest {
    private String username;
    private String password;
}

CustomUserDetailsService :

@Service
public class CustomUserDetailsService implements UserDetailsService {
    private final Map<String, String> usersMap = new HashMap<>();

    @Autowired
    public CustomUserDetailsService() {
        // Initialize the usersMap with encoded passwords
        usersMap.put("ricky", "$2a$10$Dow1SE9N1XzFxXh3YDJIoO/b0Zi4DlCg8Up7X5DpIS9b/T/xkaHOO"); // password: 123
        usersMap.put("martin", "$2a$10$Dow1SE9N1XzFxXh3YDJIoO/b0Zi4DlCg8Up7X5DpIS9b/T/xkaHOO"); // password: 456
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if (usersMap.containsKey(username)) {
            return new User(username, usersMap.get(username), new ArrayList<>()); // Empty authorities list
        }

        // If this is thrown, then we won't generate a JWT token.
        throw new UsernameNotFoundException(username + " not found.");
    }
}

Testing with Postman:

URL: http://localhost:8080/auth/login Method: POST Headers: Content-Type: application/json Body: Raw JSON Example body:

{
    "username": "ricky",
    "password": "123"
}

What I’ve Tried:

  1. Verified that the @GetMapping endpoint works.
  2. Ensured that the POST request is correctly formatted and sent with the appropriate headers.
  3. Checked that the /auth/login endpoint is permitted in the security configuration.
  4. Added request logging to see if the request is being received by Spring.
  5. Simplified the controller to rule out other potential issues.

Problem: Despite the above steps, the @PostMapping endpoint is never hit, and no error messages are logged. The @GetMapping endpoint works fine.

Additional Information: pom.xml

Any insights or suggestions on why the @PostMapping endpoint is not being hit would be greatly appreciated!


Solution

  • well of course it won't reach your method, if a Spring Security Filter returns forbidden :)

    you should also check WHY you are getting 403, set logging level to debug with logging.level.org.springframework.security=DEBUG so that you see the error.

    I am willing to bet it is CSRF which correctly doesn't allow you to send "dangerous" requests (basically any other request, except GET) without a CSRF Token.

    CSRF Option 1 for stateless Apps:

    Configure you backend to store CSRF tokens in cookies

       http.csrf(csrf -> csrf.csrfTokenRepository
                (CookieCsrfTokenRepository.withHttpOnlyFalse()));
    

    You should first send some kind of request (any request) in order to get a CSRF cookie (gets automatically added to the response of a call that doesn't have it yet) with the name (XSRF-TOKEN) and then add the value of that cookie as a X-XSRF-TOKEN header to your POST call. See here


    CSRF Option 2 turn off CSRF if your App doesn't have a session:

    If you don't rely on cookies for your authentication and don't employ session you can also consider turning off CSRF since you don't need CSRF protection without session / cookies

       http
           .csrf(AbstractHttpConfigurer::disable)
           // ...