Skip to content

Harden the public Authelia/OIDC + Caddy deployment - #7

Open
joshjowen wants to merge 1 commit into
mainfrom
claude/authelia-oidc-security-u7syce
Open

Harden the public Authelia/OIDC + Caddy deployment#7
joshjowen wants to merge 1 commit into
mainfrom
claude/authelia-oidc-security-u7syce

Conversation

@joshjowen

Copy link
Copy Markdown
Owner

Why

Follow-up to a security review of the "go-notes as an OIDC client behind Authelia + Caddy, exposed publicly" scenario. The application core came out strong — real OIDC ID-token verification (signature/nonce/state/PKCE), opaque SHA-256-at-rest revocable sessions, SameSite=Lax + Origin CSRF, a strict self-only CSP with a WASM-loader hash, content-sniffed uploads that never serve SVG inline, and structural vault isolation. The gaps were all at the operational edges of the deploy stack, and this PR closes them.

What changed

Application code

  • Placeholder-secret preflight (config.rs) — startup now refuses a recognisably unedited OIDC client_secret (CHANGE_ME/REPLACE_THIS). The example's client secret is public in this repo and its Authelia digest ships with it, so the previous "is it non-empty?" check let a copy-paste deploy run with an internet-known secret — no better than an open client for a confidential OIDC app.
  • HSTS (web.rs) — the server now emits Strict-Transport-Security itself, gated on auth.cookie_secure (so a plain-HTTP dev instance never pins a hostname to HTTPS). Previously HSTS existed only as a commented-out Caddy line.
  • go-notes logout <username> (main.rs, db.rs) — ends every server-side session for a user, reaching OIDC accounts that user remove can't touch. Group membership is only checked at sign-in, so without this a user removed from the group upstream kept access until their (up to 30-day) session expired. Now they can be cut off immediately.

Deploy stack

  • docker-compose.yml — password login is now off by default on the public stack (LOCAL_AUTH_ENABLED=false). With no forward-auth, /api/auth/login is a native go-notes endpoint that bypasses Authelia's brute-force ban and second factor entirely; leaving it on was a permanently-open single-factor door beside the hardened OIDC one. Also sets required_group so go-notes re-checks the group, not just Authelia.
  • Caddyfile — documents that HSTS is now app-emitted; adds a commented remote_ip matcher to confine break-glass /api/auth/login to LAN/VPN if you do turn it on.
  • authelia/configuration.yml — example now requires two_factor (the main reason to run Authelia).
  • config.example.toml / .env.example — spell out the trust_proxy_headers (spoofable if the app is ever reachable directly), session-TTL/deprovisioning, and local-login trade-offs.

Testing

  • cargo test -p go-notes-server173 lib + 8 airgap tests pass, including new unit tests for the placeholder detector and the HSTS helper.
  • cargo clippy -p go-notes-server — clean for all touched code (one pre-existing, unrelated lint in vault/store.rs left alone).
  • YAML for all edited compose/Authelia files validated.

No schema or API changes; the logout command reuses the existing destroy_all_for_user. Behaviour changes are confined to the shipped example deploy config and the two new startup/runtime guards described above.

🤖 Generated with Claude Code


Generated by Claude Code

Addresses the gaps found reviewing the OIDC-behind-Caddy scenario. The app
core was already strong (real OIDC verification, hashed opaque sessions,
SameSite+Origin CSRF, strict CSP, SVG-safe uploads); the weak points were the
operational edges around the deploy stack.

Code:
- config: refuse to start on a placeholder OIDC client_secret (the example's
  CHANGE_ME digest is published in this repo, so "non-empty" was not enough).
- web: emit Strict-Transport-Security when cookie_secure is on, so an HTTPS
  deployment is pinned without relying on a commented-out Caddy line; a
  plain-HTTP dev instance still sends nothing.
- cli: `go-notes logout <username>` ends every server-side session for a user,
  reaching OIDC accounts that `user remove` cannot touch — so a user removed
  from the group upstream can be cut off now rather than at session expiry.

Deploy:
- compose: password login OFF by default (it bypasses Authelia's ban and second
  factor); re-check the group in go-notes via required_group.
- caddy: document that HSTS is now app-emitted; add a commented matcher to
  confine break-glass /api/auth/login to LAN/VPN.
- authelia: example now requires two_factor.
- config/env examples: spell out the trust_proxy_headers, session TTL and
  local-login trade-offs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PoHTBZNGKEbSPhCt72BqWp
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants