auth0-spring-security5-api-sample icon indicating copy to clipboard operation
auth0-spring-security5-api-sample copied to clipboard

401 Unauthorized on POST endpoint in Spring Boot (MVC) application

Open ashishrky opened this issue 1 year ago • 8 comments

Hi, I am using Spring Boot 3 and Spring Security 6 and following the sample https://github.com/auth0-samples/auth0-spring-security5-api-sample/tree/use-spring-6/01-Authorization-MVC. Tutorial works well until I try with GET endpoints. But the moment I built a POST endpoint and call it, I get 401 Unauthorized error in postman even though this is configured to be permitted in SecurityConfig.java. Here is the link to my code changes https://github.com/ashishrky/auth0-spring-security5-api-sample/commit/8bf9866a7a18fb9d2e0c78f1950725f2f42eaee2. What’s wrong? Why GET call work just fine, but POST call get 401?

Posted in Auth0 community as well at https://community.auth0.com/t/401-unauthorized-on-post-endpoint-in-spring-boot-mvc-application/103716

ashishrky avatar Mar 30 '23 08:03 ashishrky

"hi, I have exactly the same problem, did you manage to solve yours?"

VANDRESSAGALDINOS avatar Apr 18 '23 20:04 VANDRESSAGALDINOS

If you turn up the logging for Spring Security in application.yml:

logging:
  level:
    org.springframework.security.web: DEBUG

You'll see the error when you try to do a POST:

2023-04-20T10:24:21.166-06:00 DEBUG 15786 --- [nio-3010-exec-1] o.s.security.web.FilterChainProxy        : Securing POST /api/public/post
2023-04-20T10:24:21.184-06:00 DEBUG 15786 --- [nio-3010-exec-1] o.s.security.web.csrf.CsrfFilter         : Invalid CSRF token found for http://localhost:3010/api/public/post
2023-04-20T10:24:21.184-06:00 DEBUG 15786 --- [nio-3010-exec-1] o.s.s.w.access.AccessDeniedHandlerImpl   : Responding with 403 status code
2023-04-20T10:24:21.186-06:00 DEBUG 15786 --- [nio-3010-exec-1] o.s.security.web.FilterChainProxy        : Securing POST /error
2023-04-20T10:24:21.189-06:00 DEBUG 15786 --- [nio-3010-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter  : Set SecurityContextHolder to anonymous SecurityContext

If you disable CSRF in SecurityConfig.java, everything will work:

http.csrf().disable();

Here's proof:

Screenshot 2023-04-20 at 10 34 50 AM

mraible avatar Apr 20 '23 16:04 mraible

CSRF (Cross-Site Request Forgery) is a type of attack on web applications. It happens when an attacker tricks a user into doing something they didn't intend to do on a different website where they are already logged in. Spring Boot Security uses CSRF protection to stop these tricks and keep your application safe.

In the above example, an authorized user has access only to the GetMapping method. That's why, as soon as they try to request the application with the PostMapping method, due to this CSRF, they get an unauthorised message. If we disable it, the post-mapping methods will work fine.

paulsofts avatar Oct 26 '23 10:10 paulsofts

So how do you still get CSRF protection while still being able to interact with the REST server? Is it just simple as disabling csrf for development and enabling it for production?

jo1o3o avatar Feb 15 '24 18:02 jo1o3o

SecurityFilterChain securityFilterChain(HttpSecurity http)throws Exception{ http.csrf((csrf) -> csrf.disable()) .authorizeHttpRequests((authorize)->{ authorize.requestMatchers(HttpMethod.POST,"/api/**").hasRole("ADMIN"); authorize.requestMatchers(HttpMethod.PUT,"/api/**").hasRole("ADMIN"); authorize.requestMatchers(HttpMethod.DELETE,"/api/**").hasRole("ADMIN"); authorize.anyRequest().authenticated(); }).httpBasic(Customizer.withDefaults()); return http.build(); }

In my case have already disabled it, but still getting 401 using POST from postman. However i can login using the browser.

Siddhnak avatar May 10 '24 06:05 Siddhnak

@Siddhnak In postman, you can Authorization Tab beside the Headers and add your username and password.

paulsofts avatar May 31 '24 06:05 paulsofts

@Siddhnak I am facing the same error as you did. Could you please share your knowledge if you have solved this in any manner. Thank you.

TejashwiniBusnur avatar Jul 24 '24 12:07 TejashwiniBusnur

Here's what I did to retain the basic Auth in GET request and apply CSRF in POST request:

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
        	.csrf(csrf -> csrf
        				.ignoringRequestMatchers( "/api/**")
        				.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
        				.csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler()))
        	.authorizeHttpRequests(auth -> {
                auth.anyRequest().authenticated();
        	})
            .httpBasic(Customizer.withDefaults());
        return http.build();
    }

No Auth requests in Postman produces 401 Unauthorized error and with Basic Auth the request passes through. Hope this helps!

fgluartes avatar Jul 26 '24 09:07 fgluartes