From 03d478840ba7cb3bb6ae513d3ff8ce43ef90a2ee Mon Sep 17 00:00:00 2001 From: Marcel Date: Mon, 11 May 2026 13:17:12 +0200 Subject: [PATCH] docs(arch): show Caddy + X-Forwarded-Proto in auth-flow diagram MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the Caddy hop to seq-auth-flow.puml and surfaces the two production-relevant header behaviours: - Caddy terminates TLS and forwards X-Forwarded-Proto: https - Spring Boot trusts this header (server.forward-headers-strategy: native, ForwardedRequestCustomizer at the Jetty layer), so request.getScheme() returns "https" - The Set-Cookie response carries the Secure flag because the observed scheme is https — without forward-headers-strategy this would silently drop to plain http and the cookie would lose Secure Closes the doc-currency gap flagged in the Markus review on PR #499: "Auth flow change → docs/architecture/c4/seq-auth-flow.puml". Co-Authored-By: Claude Opus 4.7 --- docs/architecture/c4/seq-auth-flow.puml | 35 ++++++++++++++++++++----- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/docs/architecture/c4/seq-auth-flow.puml b/docs/architecture/c4/seq-auth-flow.puml index bae4a831..63b9038d 100644 --- a/docs/architecture/c4/seq-auth-flow.puml +++ b/docs/architecture/c4/seq-auth-flow.puml @@ -1,26 +1,49 @@ @startuml -title Authentication Flow +title Authentication Flow (behind Caddy reverse proxy) actor User participant Browser +participant "Caddy (TLS termination)" as Caddy participant "Frontend (SvelteKit)" as Frontend participant "Backend (Spring Boot)" as Backend participant PostgreSQL as DB User -> Browser: Enter email + password -Browser -> Frontend: POST /login (form action) +Browser -> Caddy: HTTPS POST /login (form action) +note right of Caddy + Caddy terminates TLS and forwards + to Frontend over HTTP with: + X-Forwarded-Proto: https + X-Forwarded-For: + X-Forwarded-Host: archiv.raddatz.cloud +end note +Caddy -> Frontend: HTTP POST /login\n+ X-Forwarded-Proto: https Frontend -> Frontend: Base64 encode "email:password" -Frontend -> Backend: GET /api/users/me\nAuthorization: Basic +Frontend -> Backend: GET /api/users/me\nAuthorization: Basic \n+ X-Forwarded-Proto: https +note right of Backend + server.forward-headers-strategy: native + Jetty's ForwardedRequestCustomizer + reads X-Forwarded-Proto so + request.getScheme() returns "https". +end note Backend -> Backend: Spring Security parses Basic Auth Backend -> DB: SELECT user WHERE email=? DB --> Backend: AppUser + groups + permissions Backend -> Backend: BCrypt.matches(password, hash) Backend --> Frontend: 200 OK — UserDTO -Frontend -> Browser: Set-Cookie: auth_token=\n(httpOnly, SameSite=strict, maxAge=86400) -Browser -> Frontend: GET / (next request) +Frontend -> Caddy: Set-Cookie: auth_token=\n(httpOnly, **Secure**, SameSite=strict, maxAge=86400) +note right of Frontend + Secure flag is set because the + request scheme observed by the + app is https (forwarded by Caddy). +end note +Caddy -> Browser: HTTPS 200 + Set-Cookie +Browser -> Caddy: HTTPS GET / (next request) +Caddy -> Frontend: HTTP GET / + X-Forwarded-Proto: https Frontend -> Frontend: hooks.server.ts reads auth_token cookie Frontend -> Backend: GET /api/users/me\nAuthorization: Basic Backend --> Frontend: 200 OK — user in event.locals -Frontend --> Browser: Render page with user context +Frontend --> Caddy: rendered page +Caddy --> Browser: HTTPS 200 @enduml