Files
familienarchiv/docs/architecture/c4/l3-backend-3a-security.puml
Marcel 9b21d6aee8
Some checks failed
CI / Unit & Component Tests (pull_request) Successful in 3m1s
CI / OCR Service Tests (pull_request) Successful in 19s
CI / Backend Unit Tests (pull_request) Successful in 2m57s
CI / fail2ban Regex (pull_request) Successful in 42s
CI / Semgrep Security Scan (pull_request) Successful in 19s
CI / Compose Bucket Idempotency (pull_request) Successful in 1m3s
CI / Unit & Component Tests (push) Successful in 3m3s
CI / OCR Service Tests (push) Successful in 17s
CI / Backend Unit Tests (push) Successful in 2m58s
CI / fail2ban Regex (push) Successful in 42s
CI / Semgrep Security Scan (push) Successful in 19s
CI / Compose Bucket Idempotency (push) Successful in 58s
nightly / deploy-staging (push) Failing after 3m35s
docs(c4): l3-security includes auth package and Spring Session JDBC
Replace the stale Basic-Auth picture with the post-#523 model:
AuthSessionController + AuthService (the new auth/ package), Spring Session
JDBC (spring_session*, 8h idle timeout, fa_session cookie), and the
ChangeSessionIdAuthenticationStrategy bean used by login to defend against
session fixation. Addresses PR #612 / Markus M3.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 22:54:55 +02:00

31 lines
2.9 KiB
Plaintext

@startuml
!include <C4/C4_Component>
title Component Diagram: API Backend — Security & Authentication
Container(frontend, "Web Frontend", "SvelteKit")
ContainerDb(db, "PostgreSQL", "PostgreSQL 16")
System_Boundary(backend, "API Backend (Spring Boot)") {
Component(authCtrl, "AuthSessionController", "@RestController org.raddatz.familienarchiv.auth", "POST /api/auth/login validates credentials, rotates the session ID via SessionAuthenticationStrategy (CWE-384 defense), attaches the SecurityContext to the new session. POST /api/auth/logout invalidates the session unconditionally, then best-effort audits.")
Component(authSvc, "AuthService", "@Service org.raddatz.familienarchiv.auth", "Delegates credential validation to AuthenticationManager (DaoAuthenticationProvider — timing-equalised via dummy BCrypt on misses). Emits LOGIN_SUCCESS / LOGIN_FAILED / LOGOUT audit entries without ever logging the password attempt.")
Component(secFilter, "Security Filter Chain", "Spring Security", "Permits /api/auth/login, /api/auth/forgot-password, /api/auth/reset-password, /api/auth/invite/**, /api/auth/register; everything else requires an authenticated session. Returns 401 (not 302) on missing/expired session. CSRF is disabled pending #524.")
Component(sessionRepo, "Spring Session JDBC", "spring-boot-starter-session-jdbc", "Persists sessions in spring_session / spring_session_attributes (Flyway V67). 8-hour idle timeout. Cookie name fa_session, SameSite=Strict, HttpOnly, Secure behind Caddy. Indexes the session by Principal name for revocation in #524.")
Component(permAspect, "PermissionAspect", "Spring AOP", "Intercepts methods annotated with @RequirePermission. Checks the authenticated user's granted authorities against the required permission. Throws 401/403 if denied.")
Component(secConf, "SecurityConfig", "Spring @Configuration", "Wires the filter chain, BCryptPasswordEncoder, DaoAuthenticationProvider, AuthenticationManager, and the ChangeSessionIdAuthenticationStrategy bean used by AuthSessionController.")
Component(userDetails, "CustomUserDetailsService", "Spring Security UserDetailsService", "Loads AppUser by email from DB. Converts group permissions to Spring GrantedAuthority objects.")
}
Rel(frontend, authCtrl, "POST /api/auth/login + /logout", "HTTPS, JSON")
Rel(frontend, secFilter, "All other API calls", "HTTPS + fa_session cookie")
Rel(authCtrl, authSvc, "Validate creds + audit")
Rel(authCtrl, sessionRepo, "getSession() / invalidate()")
Rel(authSvc, userDetails, "Authenticates via AuthenticationManager")
Rel(secFilter, sessionRepo, "Resolves session by fa_session cookie")
Rel(secFilter, permAspect, "Authenticated requests reach guarded service methods")
Rel(secConf, userDetails, "Wires as UserDetailsService")
Rel(userDetails, db, "Loads user by email", "JDBC")
Rel(sessionRepo, db, "spring_session, spring_session_attributes", "JDBC")
@enduml