From 11d05b8963a41b4972bb899baa1ca2052d237f8a Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Sun, 2 Apr 2023 16:37:26 +0300 Subject: [PATCH 1/2] fix: Use default XOR CSRF token mechanism in Spring The stateless configuration is copied from https://docs.spring.io/spring-security/reference/5.8/migration/servlet/exploits.html#_i_am_using_angularjs_or_another_javascript_framework Fixes #14923 --- .../spring/security/VaadinWebSecurity.java | 18 ++++++------------ .../VaadinStatelessSecurityConfigurer.java | 8 ++++++++ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/vaadin-spring/src/main/java/com/vaadin/flow/spring/security/VaadinWebSecurity.java b/vaadin-spring/src/main/java/com/vaadin/flow/spring/security/VaadinWebSecurity.java index 75772717367..e8b97e12741 100644 --- a/vaadin-spring/src/main/java/com/vaadin/flow/spring/security/VaadinWebSecurity.java +++ b/vaadin-spring/src/main/java/com/vaadin/flow/spring/security/VaadinWebSecurity.java @@ -15,6 +15,12 @@ */ package com.vaadin.flow.spring.security; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import javax.crypto.SecretKey; + import java.io.IOException; import java.lang.reflect.Field; import java.util.LinkedHashMap; @@ -24,8 +30,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.crypto.SecretKey; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; @@ -54,7 +58,6 @@ import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler; import org.springframework.security.web.context.SecurityContextRepository; import org.springframework.security.web.csrf.CsrfException; -import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler; import org.springframework.security.web.savedrequest.RequestCache; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.AnyRequestMatcher; @@ -71,10 +74,6 @@ import com.vaadin.flow.server.auth.ViewAccessChecker; import com.vaadin.flow.spring.security.stateless.VaadinStatelessSecurityConfigurer; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; - /** * Provides basic Vaadin component-based security configuration for the project. *

@@ -178,11 +177,6 @@ protected void configure(HttpSecurity http) throws Exception { new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED), requestUtil::isEndpointRequest); - // Enforce the deprecated CSRF handler temporarily - // to make Hilla auth work. - http.csrf(csrf -> csrf.csrfTokenRequestHandler( - new CsrfTokenRequestAttributeHandler())); - // Vaadin has its own CSRF protection. // Spring CSRF is not compatible with Vaadin internal requests http.csrf().ignoringRequestMatchers( diff --git a/vaadin-spring/src/main/java/com/vaadin/flow/spring/security/stateless/VaadinStatelessSecurityConfigurer.java b/vaadin-spring/src/main/java/com/vaadin/flow/spring/security/stateless/VaadinStatelessSecurityConfigurer.java index 6c0bc65ab79..daac4de7845 100644 --- a/vaadin-spring/src/main/java/com/vaadin/flow/spring/security/stateless/VaadinStatelessSecurityConfigurer.java +++ b/vaadin-spring/src/main/java/com/vaadin/flow/spring/security/stateless/VaadinStatelessSecurityConfigurer.java @@ -34,7 +34,9 @@ import org.springframework.security.web.context.SecurityContextRepository; import org.springframework.security.web.csrf.CookieCsrfTokenRepository; import org.springframework.security.web.csrf.CsrfTokenRepository; +import org.springframework.security.web.csrf.CsrfTokenRequestHandler; import org.springframework.security.web.csrf.LazyCsrfTokenRepository; +import org.springframework.security.web.csrf.XorCsrfTokenRequestAttributeHandler; import org.springframework.security.web.savedrequest.CookieRequestCache; import org.springframework.security.web.savedrequest.RequestCache; @@ -98,7 +100,13 @@ public void init(H http) { // session (double-submit cookie pattern) CsrfTokenRepository csrfTokenRepository = CookieCsrfTokenRepository .withHttpOnlyFalse(); + XorCsrfTokenRequestAttributeHandler delegate = new XorCsrfTokenRequestAttributeHandler(); + + CsrfTokenRequestHandler requestHandler = delegate::handle; + csrf.csrfTokenRepository(csrfTokenRepository); + csrf.csrfTokenRequestHandler(requestHandler); + http.getSharedObject( VaadinSavedRequestAwareAuthenticationSuccessHandler.class) .setCsrfTokenRepository(csrfTokenRepository); From ab3136a2f0b34a15a8d96df277112bb6e13c8c5c Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Mon, 3 Apr 2023 18:31:48 +0300 Subject: [PATCH 2/2] Add comment --- .../stateless/VaadinStatelessSecurityConfigurer.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vaadin-spring/src/main/java/com/vaadin/flow/spring/security/stateless/VaadinStatelessSecurityConfigurer.java b/vaadin-spring/src/main/java/com/vaadin/flow/spring/security/stateless/VaadinStatelessSecurityConfigurer.java index daac4de7845..660e33be0ca 100644 --- a/vaadin-spring/src/main/java/com/vaadin/flow/spring/security/stateless/VaadinStatelessSecurityConfigurer.java +++ b/vaadin-spring/src/main/java/com/vaadin/flow/spring/security/stateless/VaadinStatelessSecurityConfigurer.java @@ -100,10 +100,11 @@ public void init(H http) { // session (double-submit cookie pattern) CsrfTokenRepository csrfTokenRepository = CookieCsrfTokenRepository .withHttpOnlyFalse(); - XorCsrfTokenRequestAttributeHandler delegate = new XorCsrfTokenRequestAttributeHandler(); + // This XorCsrfTokenRequestAttributeHandler pattern is copied from + // https://docs.spring.io/spring-security/reference/5.8/migration/servlet/exploits.html#_i_am_using_angularjs_or_another_javascript_framework + XorCsrfTokenRequestAttributeHandler delegate = new XorCsrfTokenRequestAttributeHandler(); CsrfTokenRequestHandler requestHandler = delegate::handle; - csrf.csrfTokenRepository(csrfTokenRepository); csrf.csrfTokenRequestHandler(requestHandler);