---
name: auth-feature
description: Login + refresh + logout + password reset + MFA-ready scaffolding.
---

# Blueprint: Auth Feature

## Frontend

- Routes: `/auth/login`, `/auth/forgot-password`, `/auth/reset-password`, `/auth/mfa`.
- Services: `AuthService` (signals), `CurrentUserService`, `PermissionService`.
- Interceptors: `auth.interceptor` (Bearer) + `error.interceptor` (401→logout) + `correlation-id`.
- Guards: `authGuard`, `permissionGuard(...perms)`.

## Backend

- `.NET API owns issuance`: `/api/auth/login`, `/refresh`, `/logout`, `/me`, `/forgot-password`, `/reset-password`.
- `Argon2PasswordHasher` for storage; `JwtService` issues 15-min access tokens; `RefreshTokenService` rotates 30-day refresh tokens (hashed in DB).
- Node hosts verify via `@loma-portal/em-auth` (JwtVerifierService).

## Database

- `User` (with `passwordHash`, `lastLoginAt`).
- `RefreshToken` (hashed, with `revokedAt`, `replacedByTokenHash`, `ipAddress`, `userAgent`).

## API contract

- `loginRequestSchema`, `loginResponseSchema`, `refreshRequestSchema`, `authTokensSchema`.

## UI

- Glass-card login (token-driven), TH/EN, accessibility AA.
- Loading state during sign-in; error toast on failure.

## Validation

- Email format + min password length client+server.
- Rate-limit login attempts (throttler).

## Testing

- `LoginCommandValidator` test (input shape).
- Argon2 hash round-trip test.
- E2E login → dashboard via Playwright.

## Observability

- Audit `auth.login` / `auth.login_failed` / `auth.refresh` / `auth.logout` / `auth.password_reset`.

## Security

- Argon2id, secrets ≥ 32 chars (env-validated).
- Refresh tokens stored as SHA-256 hash.
- No raw tokens logged.
- Lock account / step-up MFA on repeated failure (future).
