RestController POST fails with error 403

I love Vaadin because of the intergrated login/logout-flow, but I’m always struggling to configure Spring Security for extended use-cases…

In the app I’m working on, I also need a few public REST controllers to handle POST requests. Whatever I try, they always block on 403, while GET requests work perfectly. Any idea what is wrong with my Spring Security configuration?

Spring Boot 3.2.5
Vaadin 24.3.12

@EnableWebSecurity
@Configuration
public class SecurityConfiguration extends VaadinWebSecurity {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(
                authorize -> authorize.requestMatchers(
                        new AntPathRequestMatcher("/api/**"),
                        new AntPathRequestMatcher("/images/**")
                ).permitAll());

        // Icons from the line-awesome addon
        http.authorizeHttpRequests(authorize -> authorize
                .requestMatchers(new AntPathRequestMatcher("/line-awesome/**/*.svg")).permitAll());

        super.configure(http);
        setLoginView(http, LoginView.class);
    }
}

I already tried with adding .csrf(AbstractHttpConfigurer::disable) and @PermitAll on the REST controller.

Thanks
Frank

Did you try to set org.springframework.security logger category to DEBUG level? It might provide additional hints to understand who is blocking the request.

1 Like

No solution, but you can upvote Create a Spring + Vaadin + REST example · Issue #2504 · vaadin/docs · GitHub :smirk:

2 Likes

Thanks for the tip… Shows that CSRF is the problem.

2024-06-05T13:05:02.263+02:00 DEBUG 40069 --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy        : Securing POST /api/callback
2024-06-05T13:05:02.264+02:00 DEBUG 40069 --- [nio-8080-exec-5] o.s.security.web.csrf.CsrfFilter         : Invalid CSRF token found for http://localhost:8080/api/callback
2024-06-05T13:05:02.265+02:00 DEBUG 40069 --- [nio-8080-exec-5] o.s.s.w.access.AccessDeniedHandlerImpl   : Responding with 403 status code
2024-06-05T13:05:02.266+02:00 DEBUG 40069 --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy        : Securing POST /error
2024-06-05T13:05:02.266+02:00 DEBUG 40069 --- [nio-8080-exec-5] o.s.s.w.a.AnonymousAuthenticationFilter  : Set SecurityContextHolder to anonymous SecurityContext
2024-06-05T13:05:02.266+02:00 DEBUG 40069 --- [nio-8080-exec-5] s.w.a.DelegatingAuthenticationEntryPoint : Trying to match using com.vaadin.flow.spring.security.VaadinWebSecurity$$Lambda/0x00003fc001bdcb20@e5c9f16
2024-06-05T13:05:02.266+02:00 DEBUG 40069 --- [nio-8080-exec-5] s.w.a.DelegatingAuthenticationEntryPoint : Trying to match using any request
2024-06-05T13:05:02.267+02:00 DEBUG 40069 --- [nio-8080-exec-5] s.w.a.DelegatingAuthenticationEntryPoint : Match found! Executing org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint@15d42077
2024-06-05T13:05:02.267+02:00 DEBUG 40069 --- [nio-8080-exec-5] o.s.s.web.DefaultRedirectStrategy        : Redirecting to http://localhost:8080/login
2024-06-05T13:05:02.269+02:00 DEBUG 40069 --- [nio-8080-exec-7] o.s.security.web.FilterChainProxy        : Securing GET /login
2024-06-05T13:05:02.269+02:00 DEBUG 40069 --- [nio-8080-exec-7] o.s.s.w.a.AnonymousAuthenticationFilter  : Set SecurityContextHolder to anonymous SecurityContext
2024-06-05T13:05:02.269+02:00 DEBUG 40069 --- [nio-8080-exec-7] o.s.security.web.FilterChainProxy        : Secured GET /login

But how to fix this? Adding this to the SecurityConfiguration doesn’t change the behavior:

http.csrf(AbstractHttpConfigurer::disable);

If I remember correctly the order is important… before or after the super call

2 Likes

before the super call → POST still 403
after the super call → Vaadin website doesn’t work ;-)

Adding the csrf before super call, works for me

http.authorizeHttpRequests(
        authorize -> authorize.requestMatchers(
                antMatchers("/images/**", "/api/**")
        ).permitAll());
http.csrf(csrf -> csrf.ignoringRequestMatchers(antMatchers("/api/**")));
super.configure(http);
...
1 Like

Thanks a lot, indeed this is the correct configuration I was looking for. You made my day :-) Because of deprecated warnings related to Spring Security 6.1 it was not clear exactly what I needed to use…

Hi @marcoc_753

I really hate to be the guy who destroy parties, but when it comes to security, I can not hold myself.

your “hack” works because you technically disabled spring security for the "api’ endpoint at all.

The reason of the 403 @frank.63 got was because he was not logged in.

@frank.63

you either need to implement login using jwt token, or login page.

I think i have read some articles in vaadin blog, but cannot recall now.

In production this hack will be like locking your car doors and leaving all windows open.

Note :: Disabling CSRF is allowed only if your are using pure API gateway(eg stand alone)

Vaadin does provide its own CSRF mechanism - so the one of Spring is literally useless in a Vaadin application. Only time it’s needed is with a native login form or additional JSP or other files served next to Vaadin (but nobody should do this anyway).

Hi @ecohen280,
I get your points about security, but in this particular case I partially agree:

  • in the initial post, the /api/ endpoints were already declared public
  • the posted logs clearly state that the issue was an invalid CSRF token for a POST request on /api/callback, not a missing authentication
  • the CSRF is disabled only for the APIs (and for Vaadin internal requests that, how @knoobie said, are already protected by Vaadin mechanism).

Whether API should be protected or not depends on the application, so only @frank.63 knows :slight_smile:
Maybe they should, but the posted configuration was only a first POC of making Spring Controllers work together with Vaadin.

Anyway, thanks for your feedback.

1 Like

Thanks all for your feedback!

Indeed I know I shouldn’t disable csrf but that’s the only solution I found now… And my APIs don’t need authentication (yet), there are only which will provide public info only.

Anyhow, that being said… It’s not the first time I hit the “Vaadin+Spring security wall” and there are many like me. So I guess this topic needs some love, either with better examples and documentation or a different implementation…