feat(security): CSRF protection, session revocation, login rate limiting (#524) #617

Merged
marcel merged 26 commits from feat/issue-524-csrf-session-rate-limit into main 2026-05-19 09:23:03 +02:00
Showing only changes of commit c3d1bea623 - Show all commits

View File

@@ -32,6 +32,11 @@ import java.util.Map;
@RequiredArgsConstructor
public class SecurityConfig {
// @WebMvcTest slices do not include JacksonAutoConfiguration, so ObjectMapper
// cannot be injected here. A static instance is safe because the response
// only serializes fixed String keys — no custom naming strategy or module needed.
private static final ObjectMapper ERROR_WRITER = new ObjectMapper();
private final CustomUserDetailsService userDetailsService;
private final Environment environment;
@@ -88,7 +93,7 @@ public class SecurityConfig {
// CSRF protection via CookieCsrfTokenRepository (NFR-SEC-103).
// The backend sets an XSRF-TOKEN cookie (not HttpOnly so JS can read it).
// All state-changing requests must include X-XSRF-TOKEN matching the cookie.
// See ADR-020 and issue #524 for the full security rationale.
// See ADR-022 and issue #524 for the full security rationale.
.csrf(csrf -> csrf
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler()))
@@ -127,7 +132,7 @@ public class SecurityConfig {
ErrorCode code = (e instanceof CsrfException)
? ErrorCode.CSRF_TOKEN_MISSING
: ErrorCode.FORBIDDEN;
res.getWriter().write(new ObjectMapper().writeValueAsString(Map.of("code", code.name())));
res.getWriter().write(ERROR_WRITER.writeValueAsString(Map.of("code", code.name())));
}));
return http.build();