⚠️ Potential issue | 🔴 Critical | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate and print the relevant config with line numbers
FILE="bff/src/main/java/org/example/bff/config/BffConfig.java"
if [ -f "$FILE" ]; then
echo "== $FILE =="
nl -ba "$FILE" | sed -n '1,140p'
else
echo "Missing $FILE"
fi
# Search for CSRF disable and any other security config affecting CSRF/session
echo "== rg: csrf.disable =="
rg -n "csrf\s*\(\s*[^)]*disable\s*\(\s*\)\s*\)|csrf\s*\.disable\s*\(|csrf\s*->\s*.*disable" -S .
echo "== rg: authorizeHttpRequests/auth anyRequest =="
rg -n "authorizeHttpRequests|anyRequest\(\)\.authenticated\(\)" -S bff/src/main/java || true
echo "== rg: oauth2Login or sessionManagement =="
rg -n "oauth2Login|oauth2Client|sessionManagement|SessionCreationPolicy|JSESSIONID" -S bff/src/main/java || true
echo "== Files with security filter chain =="
rg -n "SecurityFilterChain|HttpSecurity" -S bff/src/main/java/org/example/bff/config || true
Repository: simonforsberg/relay
Length of output: 186
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE="bff/src/main/java/org/example/bff/config/BffConfig.java"
echo "== repo files (bff config path existence) =="
ls -la bff/src/main/java/org/example/bff/config/ 2>/dev/null || true
if [ -f "$FILE" ]; then
echo "Found: $FILE"
else
echo "Missing: $FILE"
# Fallback: locate similarly named files
echo "== locating BffConfig.java =="
fd -a "BffConfig.java" . || true
fi
if [ -f "$FILE" ]; then
echo "== showing lines 1-120 with numbers (cat -n) =="
cat -n "$FILE" | sed -n '1,140p'
echo "== rg: csrf.disable patterns =="
rg -n "csrf\s*\(.*\)|csrf\.disable\(\)|csrf\s*->.*disable" -S "$FILE" || true
echo "== rg: oauth2Login/session auth hints =="
rg -n "oauth2Login|oauth2Client|sessionManagement|JSESSIONID|CookieCsrfTokenRepository|csrfTokenRepository" -S "$FILE" || true
echo "== locate SecurityFilterChain(s) in config package =="
rg -n "SecurityFilterChain|HttpSecurity" -S bff/src/main/java/org/example/bff/config || true
fi
Repository: simonforsberg/relay
Length of output: 4621
🌐 Web query:
Spring Security OAuth2Login stores authentication in HttpSession by default
💡 Result:
Yes—by default, Spring Security OAuth2 login for Servlet (oauth2Login) saves the authenticated user’s SecurityContext in the HttpSession, which effectively stores the Authentication in HttpSession. This is because Spring Security uses a SecurityContextRepository to persist the SecurityContext between requests, and the documented default mechanism is HttpSessionSecurityContextRepository, which “associates the SecurityContext to the HttpSession” [1]. During OAuth2 login, after the Authorization Response is successfully processed and an OAuth2AuthenticationToken is created, it is “ultimately stored in the SecurityContextRepository” [2]. With the default SecurityContextRepository setup, that repository persists to HttpSession via HttpSessionSecurityContextRepository [1]. Note: your query mentions “Spring Security OAuth2Login” generically; the sources above are for Servlet-based Spring Security. For Reactive (WebFlux), the equivalent defaults use a WebSession-backed repository instead of HttpSession [3].
Citations:
🌐 Web query:
CookieCsrfTokenRepository default cookie/header names XSRF-TOKEN X-XSRF-TOKEN X-CSRF-TOKEN
💡 Result:
In Spring Security, the CookieCsrfTokenRepository (and its reactive equivalent, CookieServerCsrfTokenRepository) uses the following default names, which are designed to follow AngularJS conventions [1][2][3][4]: - Cookie Name: XSRF-TOKEN [1][2][4] - Header Name: X-XSRF-TOKEN [1][2][4] The repository persists the CSRF token in a cookie named "XSRF-TOKEN" and reads the token from the "X-XSRF-TOKEN" HTTP header during request validation [1][2]. By default, the cookie created by this repository has the HttpOnly flag set to true to enhance security by preventing client-side JavaScript access [2][4][5]. However, because many single-page application (SPA) frameworks (like AngularJS or other custom JavaScript-based clients) need to read this cookie value to set it in the required HTTP request header, Spring Security provides the.withHttpOnlyFalse factory method [1][6][3][7]. Using this method allows JavaScript running on the client to read the cookie so it can be manually included in the X-XSRF-TOKEN header for subsequent requests [6][7].
Citations:
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# find other security configs in repo
rg -n "SecurityFilterChain|HttpSecurity|csrf\(|csrf\.|oauth2Login|logout\(|LogoutConfigurer" -S bff/src/main/java || true
# specifically look for logout request matcher overrides
rg -n "logoutRequestMatcher|LogoutRequestMatcher|LogoutConfigurer|postOnly|LogoutConfigurer" -S . || true
Repository: simonforsberg/relay
Length of output: 772
Re-enable CSRF protection for the session-backed BFF (bff/src/main/java/org/example/bff/config/BffConfig.java:38-43)
This disables CSRF (.csrf(csrf -> csrf.disable())) while oauth2Login(Customizer.withDefaults()) uses the default HttpSessionSecurityContextRepository, so authenticated requests to the BFF (including logout and proxied state-changing POST/DELETE routes) are no longer protected against cross-site request forgery.
🛡️ Proposed fix
+import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
...
- .csrf(csrf -> csrf.disable())
+ .csrf(csrf -> csrf
+ .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()))
Frontend should read the XSRF-TOKEN cookie and send it back as the X-XSRF-TOKEN header on POST/DELETE requests.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated())
.csrf(csrf -> csrf
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()))
.oauth2Login(Customizer.withDefaults())
.oauth2Client(Customizer.withDefaults())
.logout(logout -> logout
.logoutSuccessHandler(logoutSuccessHandler)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@bff/src/main/java/org/example/bff/config/BffConfig.java` around lines 39 -
45, The CSRF protection was disabled in BffConfig which leaves session-backed
oauth2Login and state-changing routes vulnerable; re-enable CSRF by removing the
csrf().disable() call and configure a CookieCsrfTokenRepository (e.g., in the
csrf(...) lambda call, set
csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())) so the
server emits an XSRF-TOKEN cookie and accepts the X-XSRF-TOKEN header from the
frontend; keep the existing oauth2Login(...) and logout(logout ->
logout.logoutSuccessHandler(logoutSuccessHandler)) configuration unchanged so
logout and proxied POST/DELETE routes are protected while the frontend reads the
XSRF-TOKEN cookie and sends it as X-XSRF-TOKEN.
Originally posted by @coderabbitai[bot] in #6 (comment)
🧩 Analysis chain
🏁 Script executed:
Repository: simonforsberg/relay
Length of output: 186
🏁 Script executed:
Repository: simonforsberg/relay
Length of output: 4621
🌐 Web query:
Spring Security OAuth2Login stores authentication in HttpSession by default💡 Result:
Yes—by default, Spring Security OAuth2 login for Servlet (oauth2Login) saves the authenticated user’s SecurityContext in the HttpSession, which effectively stores the Authentication in HttpSession. This is because Spring Security uses a SecurityContextRepository to persist the SecurityContext between requests, and the documented default mechanism is HttpSessionSecurityContextRepository, which “associates the SecurityContext to the HttpSession” [1]. During OAuth2 login, after the Authorization Response is successfully processed and an OAuth2AuthenticationToken is created, it is “ultimately stored in the SecurityContextRepository” [2]. With the default SecurityContextRepository setup, that repository persists to HttpSession via HttpSessionSecurityContextRepository [1]. Note: your query mentions “Spring Security OAuth2Login” generically; the sources above are for Servlet-based Spring Security. For Reactive (WebFlux), the equivalent defaults use a WebSession-backed repository instead of HttpSession [3].
Citations:
🌐 Web query:
CookieCsrfTokenRepository default cookie/header names XSRF-TOKEN X-XSRF-TOKEN X-CSRF-TOKEN💡 Result:
In Spring Security, the CookieCsrfTokenRepository (and its reactive equivalent, CookieServerCsrfTokenRepository) uses the following default names, which are designed to follow AngularJS conventions [1][2][3][4]: - Cookie Name: XSRF-TOKEN [1][2][4] - Header Name: X-XSRF-TOKEN [1][2][4] The repository persists the CSRF token in a cookie named "XSRF-TOKEN" and reads the token from the "X-XSRF-TOKEN" HTTP header during request validation [1][2]. By default, the cookie created by this repository has the HttpOnly flag set to true to enhance security by preventing client-side JavaScript access [2][4][5]. However, because many single-page application (SPA) frameworks (like AngularJS or other custom JavaScript-based clients) need to read this cookie value to set it in the required HTTP request header, Spring Security provides the.withHttpOnlyFalse factory method [1][6][3][7]. Using this method allows JavaScript running on the client to read the cookie so it can be manually included in the X-XSRF-TOKEN header for subsequent requests [6][7].
Citations:
🏁 Script executed:
Repository: simonforsberg/relay
Length of output: 772
Re-enable CSRF protection for the session-backed BFF (bff/src/main/java/org/example/bff/config/BffConfig.java:38-43)
This disables CSRF (
.csrf(csrf -> csrf.disable())) whileoauth2Login(Customizer.withDefaults())uses the default HttpSessionSecurityContextRepository, so authenticated requests to the BFF (including logout and proxied state-changing POST/DELETE routes) are no longer protected against cross-site request forgery.🛡️ Proposed fix
Frontend should read the
XSRF-TOKENcookie and send it back as theX-XSRF-TOKENheader on POST/DELETE requests.📝 Committable suggestion
🤖 Prompt for AI Agents
Originally posted by @coderabbitai[bot] in #6 (comment)