diff --git a/DESIGN_CONSIDERATIONS.md b/DESIGN_CONSIDERATIONS.md index ba67f4a..a959808 100644 --- a/DESIGN_CONSIDERATIONS.md +++ b/DESIGN_CONSIDERATIONS.md @@ -2,151 +2,151 @@ ## Summary -Preauth is a well-architected TOTP-based authentication gateway that has evolved from a single-file script into a clean, event-listener-driven Symfony application with 100% test coverage. The codebase demonstrates strong security fundamentals (host-prefixed cookies, nonce-based replay protection, rate limiting, backup code system) and thoughtful operational design (dual-layer cache with change tracking, FrankenPHP worker mode). The following observations focus on areas where modern best practices could further strengthen the project, organized by category and prioritized by impact. +Preauth is a well-architected TOTP-based authentication gateway that has evolved from a single-file script into a clean, event-listener-driven Symfony application with 100% test coverage. The codebase demonstrates strong security fundamentals (host-prefixed cookies, nonce-based replay protection, rate limiting, backup code system) and thoughtful operational design (dual-layer cache with change tracking, FrankenPHP worker mode). + +This document was originally prepared as a design review. Items that have been addressed are marked with ✅ and include a reference to the commit or change that resolved them. Items still open are marked with ⬜ and remain as recommendations for future work. --- ## 1. Security -### 1.1 Missing Security Response Headers [HIGH PRIORITY] +### 1.1 Missing Security Response Headers [HIGH PRIORITY] ✅ Addressed -**Current state:** Responses are sent without standard security headers. There is no `X-Content-Type-Options: nosniff`, `X-Frame-Options: DENY`, `Content-Security-Policy`, `Referrer-Policy`, or `Permissions-Policy` header on any response — whether the login page HTML, JSON API responses, or plain-text auth-success responses. +**Current state:** Fixed. A `SecurityHeadersListener` (response event, priority 0) now sets the following headers on all main-request responses: -**Suggestion:** Add a simple event listener (or a `ResponseEvent` subscriber) that sets these headers on all responses. A baseline set would be: ``` X-Content-Type-Options: nosniff X-Frame-Options: DENY Content-Security-Policy: default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline' -Referrer-Policy: no-referrer +Referrer-Policy: strict-origin-when-cross-origin +Strict-Transport-Security: max-age=31536000 ``` -**Why:** As an authentication gateway, preauth's responses are seen by every unauthenticated client. Without `X-Frame-Options: DENY`, the login page could be embedded in an iframe for clickjacking. Without `X-Content-Type-Options: nosniff`, browsers may MIME-sniff responses and misinterpret content. The inline `