docs(adr): convert all ADRs to MADR 2.1.2 format
Rewrites all 12 frontend ADRs from a custom structure to the MADR 2.1.2 template required by the VS Code ADR Manager extension: bullet metadata (Status/Date), standardised section headings, "Chosen option: X, because Y" wording, and explicit Pros/Cons blocks per option.
This commit is contained in:
@@ -1,26 +1,48 @@
|
||||
# ADR 0005: JWT Authentication Stored in localStorage
|
||||
# Store JWT authentication token in localStorage
|
||||
|
||||
**Date:** 2026-04-26
|
||||
**Status:** Accepted
|
||||
- Status: accepted
|
||||
- Date: 2026-04-26
|
||||
|
||||
## Context
|
||||
## Context and Problem Statement
|
||||
|
||||
The application requires persistent authentication across browser sessions. The two main options for token storage are:
|
||||
The application requires persistent authentication across browser sessions. Where should the JWT token be stored client-side?
|
||||
|
||||
- **`localStorage`** — accessible via JavaScript; survives tab/window close; vulnerable to XSS.
|
||||
- **httpOnly cookies** — inaccessible to JavaScript; protected from XSS; requires CSRF protection.
|
||||
## Decision Drivers
|
||||
|
||||
The application is not publicly accessible — it is used internally by a known, controlled user base. The attack surface for XSS is limited.
|
||||
- Application is internal — used by a known, controlled user base; not publicly accessible.
|
||||
- Implementation simplicity.
|
||||
- Compatibility with Angular functional guards and the APP_INITIALIZER auth bootstrap.
|
||||
|
||||
## Decision
|
||||
## Considered Options
|
||||
|
||||
Store the JWT token in `localStorage` under the key `jwtToken`. `JwtService` handles read/write/delete operations. `UserService` exposes `currentUser` (BehaviorSubject) and `isAuthenticated` (ReplaySubject) observables consumed by guards and the layout.
|
||||
- Store JWT in localStorage
|
||||
- Store JWT in an httpOnly cookie
|
||||
|
||||
An `APP_INITIALIZER` in `app.config.ts` calls `userService.getCurrentUser()` on startup if a token exists, ensuring guards can rely on `isAuthenticated` being populated before the first navigation.
|
||||
## Decision Outcome
|
||||
|
||||
## Consequences
|
||||
Chosen option: "Store JWT in localStorage", because the application is internal with a controlled user base, making the XSS risk acceptable, and localStorage avoids the additional CSRF complexity of cookie-based auth.
|
||||
|
||||
- **Positive:** Simple implementation. No server-side session management. Works seamlessly with Angular's functional guards.
|
||||
- **Positive:** Token persists across browser restarts without requiring re-login.
|
||||
- **Risk:** XSS attacks could exfiltrate the token. Acceptable given the non-public nature of the application.
|
||||
- **Future consideration:** If the application becomes publicly accessible or handles sensitive data, migrate to httpOnly cookies with CSRF tokens.
|
||||
### Positive Consequences
|
||||
|
||||
- Simple implementation — no server-side session management.
|
||||
- Token persists across browser restarts without requiring re-login.
|
||||
- Works seamlessly with Angular functional guards and `APP_INITIALIZER`.
|
||||
|
||||
### Negative Consequences
|
||||
|
||||
- Accessible to JavaScript — an XSS attack could exfiltrate the token.
|
||||
- If the application ever becomes publicly accessible or handles sensitive data, this decision must be revisited.
|
||||
|
||||
## Pros and Cons of the Options
|
||||
|
||||
### Store JWT in localStorage
|
||||
|
||||
- Good, because simple to implement and operate.
|
||||
- Good, because survives browser restarts.
|
||||
- Bad, because XSS-vulnerable.
|
||||
|
||||
### Store JWT in an httpOnly cookie
|
||||
|
||||
- Good, because inaccessible to JavaScript — XSS-safe.
|
||||
- Bad, because requires CSRF protection (SameSite cookie policy or CSRF tokens).
|
||||
- Bad, because more complex server-side coordination.
|
||||
|
||||
Reference in New Issue
Block a user