Spring Security
HTTP Methods
POST PUT DELETE
Java
Web Security

How to enable POST, PUT AND DELETE methods in spring security

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Spring Security, POST, PUT, and DELETE are not usually “disabled” in a global sense. The real issue is that state-changing requests are often blocked by security rules, most commonly authorization rules or CSRF protection, so enabling them means configuring the security chain correctly for the kind of application you are building.

What Usually Blocks These Methods

When developers say “GET works but POST, PUT, and DELETE do not,” the cause is usually one of these:

  • the request is not authorized for that path or method
  • CSRF protection rejects the request
  • CORS preflight is not configured for browser clients

So the fix is not just to “allow methods.” It is to match the HTTP method, path, and authentication model correctly.

Authorizing by HTTP Method

In modern Spring Security, use a SecurityFilterChain bean and method-specific request matchers.

java
1import org.springframework.context.annotation.Bean;
2import org.springframework.context.annotation.Configuration;
3import org.springframework.http.HttpMethod;
4import org.springframework.security.config.Customizer;
5import org.springframework.security.config.annotation.web.builders.HttpSecurity;
6import org.springframework.security.web.SecurityFilterChain;
7
8@Configuration
9public class SecurityConfig {
10
11    @Bean
12    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
13        http
14            .authorizeHttpRequests(auth -> auth
15                .requestMatchers(HttpMethod.GET, "/api/items/**").permitAll()
16                .requestMatchers(HttpMethod.POST, "/api/items/**").hasRole("EDITOR")
17                .requestMatchers(HttpMethod.PUT, "/api/items/**").hasRole("EDITOR")
18                .requestMatchers(HttpMethod.DELETE, "/api/items/**").hasRole("ADMIN")
19                .anyRequest().authenticated()
20            )
21            .httpBasic(Customizer.withDefaults());
22
23        return http.build();
24    }
25}

This does not disable any method. It defines who may use each method on a given route.

CSRF Is the Common Surprise

By default, Spring Security protects browser-based state-changing requests with CSRF checks. That means:

  • 'GET usually works'
  • 'POST, PUT, and DELETE may fail with 403'

If you are building a stateless REST API for non-browser clients and using tokens instead of session cookies, it is common to disable CSRF:

java
1import org.springframework.context.annotation.Bean;
2import org.springframework.context.annotation.Configuration;
3import org.springframework.http.HttpMethod;
4import org.springframework.security.config.annotation.web.builders.HttpSecurity;
5import org.springframework.security.web.SecurityFilterChain;
6
7@Configuration
8public class SecurityConfig {
9
10    @Bean
11    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
12        http
13            .csrf(csrf -> csrf.disable())
14            .authorizeHttpRequests(auth -> auth
15                .requestMatchers(HttpMethod.POST, "/api/**").authenticated()
16                .requestMatchers(HttpMethod.PUT, "/api/**").authenticated()
17                .requestMatchers(HttpMethod.DELETE, "/api/**").authenticated()
18                .anyRequest().permitAll()
19            );
20
21        return http.build();
22    }
23}

Do this only when it matches your authentication model. If you are using browser sessions and cookies, disabling CSRF casually is usually the wrong move.

CORS for Browser Clients

If the client is a browser app hosted on another origin, the problem may be CORS rather than Spring Security method authorization. In that case, add CORS support explicitly.

java
1import java.util.List;
2import org.springframework.context.annotation.Bean;
3import org.springframework.context.annotation.Configuration;
4import org.springframework.web.cors.CorsConfiguration;
5import org.springframework.web.cors.CorsConfigurationSource;
6import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
7
8@Configuration
9public class CorsConfig {
10
11    @Bean
12    public CorsConfigurationSource corsConfigurationSource() {
13        CorsConfiguration config = new CorsConfiguration();
14        config.setAllowedOrigins(List.of("http://localhost:3000"));
15        config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
16        config.setAllowedHeaders(List.of("*"));
17
18        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
19        source.registerCorsConfiguration("/**", config);
20        return source;
21    }
22}

Then enable it in the security chain with http.cors(...).

A Full REST-Style Example

java
1import org.springframework.context.annotation.Bean;
2import org.springframework.context.annotation.Configuration;
3import org.springframework.security.config.Customizer;
4import org.springframework.security.config.annotation.web.builders.HttpSecurity;
5import org.springframework.security.web.SecurityFilterChain;
6
7@Configuration
8public class SecurityConfig {
9
10    @Bean
11    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
12        http
13            .csrf(csrf -> csrf.disable())
14            .cors(Customizer.withDefaults())
15            .authorizeHttpRequests(auth -> auth
16                .requestMatchers("/api/public/**").permitAll()
17                .requestMatchers("/api/**").authenticated()
18                .anyRequest().denyAll()
19            )
20            .httpBasic(Customizer.withDefaults());
21
22        return http.build();
23    }
24}

In this style, authenticated clients can use the protected API routes with all needed HTTP methods, assuming the controller mappings exist.

Common Pitfalls

One common mistake is blaming Spring Security method support when the real failure is CSRF. A 403 on POST with a working GET often points there first.

Another issue is allowing the method in authorization rules but forgetting browser CORS configuration, which makes the request fail before it reaches the controller.

A third pitfall is disabling CSRF without understanding whether the application still uses cookie-based browser sessions.

Summary

  • 'POST, PUT, and DELETE are usually blocked by security rules, not globally disabled.'
  • Use method-specific request matchers to authorize those methods cleanly.
  • For stateless APIs, disabling CSRF is common; for session-based browser apps, be more careful.
  • Configure CORS when browser clients call the API from another origin.
  • Check authorization, CSRF, and CORS before assuming the HTTP method itself is the problem.

Course illustration
Course illustration

All Rights Reserved.