4.1 KiB
Research: Basic Login Protection
Feature: 003-basic-login
Date: 2026-04-06
Finding 1: Backend Auth Mechanism — Already Implemented
Decision: Keep existing HTTP Basic Auth (Spring Security, SecurityConfig.java).
Rationale: Spring Security with HTTP Basic is already configured and working. The backend validates credentials on every API request. There is nothing to add except making the username configurable and adding a credential-check endpoint.
Alternatives considered: Form-based login with server-side sessions — rejected because it adds session management complexity on the backend that is unnecessary for an SPA using HTTP Basic.
Finding 2: Frontend Credential Storage — sessionStorage
Decision: Store entered username and password in browser sessionStorage via a Pinia store.
Rationale:
sessionStoragepersists across page refreshes (same tab) but is cleared when the tab is closed — this matches the expected session behavior (SC-004) without needing a server-side session or JWT.- Simpler than
localStorage(no explicit logout needed to clear on browser close). - No additional dependencies required.
Alternatives considered:
localStorage— rejected: credentials would persist indefinitely across browser sessions, which is unexpected for a "login" flow.- In-memory (reactive ref only) — rejected: credentials lost on page refresh, violating SC-004.
- Cookie-based session (server-side) — rejected: requires CSRF protection, session store, and more backend complexity; violates KISS.
Finding 3: Credential Verification — Lightweight Backend Endpoint
Decision: Add GET /api/v1/auth/check that returns 200 OK with {"username": "..."} for authenticated requests.
Rationale: The frontend needs a way to verify that stored credentials are valid when the app loads (e.g., after a refresh). Without this, the first real API call would fail with a 401 and force a re-login on every refresh if credentials changed. This endpoint is protected by Spring Security like all others — no special logic needed.
Alternatives considered:
- Re-use any existing GET endpoint (e.g.,
GET /api/v1/books) — rejected: couples auth verification to a business endpoint; semantically wrong and fragile. - Intercept 401s globally and redirect to login — used as a fallback but not sufficient alone: the user would see a flash of the main UI before being redirected.
Finding 4: Axios Integration — Request Interceptor
Decision: Replace the hardcoded auth field in api.ts with a dynamic request interceptor that reads credentials from the Pinia auth store at request time.
Rationale: The current api.ts sets auth: { username, password } once at module initialisation from env vars. This must change so the login form's entered credentials are used. A request interceptor reads the store on every call, enabling logout (clear store → next request gets no credentials → 401 → redirect to login).
Alternatives considered:
- Recreate the axios instance after login — rejected: all existing services import the singleton
api; recreating would require updating every import.
Finding 5: Backend Username Configurability
Decision: Read username from ${app.auth.username:neurosurgeon} in SecurityConfig.java (with "neurosurgeon" as default).
Rationale: The spec (FR-012) requires credentials to be configurable. Currently the password is configurable via env var but the username is hardcoded. Adding a @Value-injected username field is a one-line change.
Alternatives considered: None — this is the Spring Boot idiomatic approach already used for the password.
Summary of Unknowns Resolved
| Unknown | Resolution |
|---|---|
| Where to store credentials on the frontend | sessionStorage via Pinia |
| How to verify credentials after page refresh | GET /api/v1/auth/check endpoint |
| How to inject credentials into axios | Request interceptor in api.ts |
| How to handle 401s globally | Response interceptor → redirect to /login |
| Backend username configurability | @Value("${app.auth.username:neurosurgeon}") |