# 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**: - `sessionStorage` persists 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}")` |