Finishes functional design for unit 0 (back-end changes before front-end work)
This commit is contained in:
+53
@@ -0,0 +1,53 @@
|
||||
# NFR Requirements — Unit 0: Backend Prerequisites
|
||||
|
||||
## NFR-U0-01: Security — httpOnly Cookie (SECURITY-12)
|
||||
- Refresh token MUST be stored in an httpOnly, Secure (request.IsHttps), SameSite=Strict cookie
|
||||
- Access token MUST NOT be returned in persistent storage; only in response body and in-memory on client
|
||||
- See `business-rules.md` BR-U0-02, BR-U0-03 for detailed cookie specification
|
||||
|
||||
## NFR-U0-02: Security — CORS (SECURITY-08)
|
||||
- CORS MUST use explicit origin allowlist from configuration — no wildcard origins
|
||||
- `AllowCredentials()` MUST be set to allow the refresh token cookie to be sent cross-origin
|
||||
- CORS middleware MUST be registered before `UseAuthentication` in the pipeline
|
||||
- An empty `AllowedOrigins` array in production configuration is a safe default (no SPA access)
|
||||
|
||||
## NFR-U0-03: Security — Rate Limiting (SECURITY-11)
|
||||
- The `POST /api/v1/auth/login` and `POST /api/v1/auth/refresh` endpoints MUST have rate limiting
|
||||
- **Implementation**: ASP.NET Core built-in `RateLimiter` middleware (available in .NET 7+)
|
||||
- **Policy**: Fixed window — max **5 requests per 1 minute per IP address** on login endpoint
|
||||
- **Policy**: Sliding window — max **20 requests per 1 minute per IP address** on refresh endpoint
|
||||
- Exceeded rate limit returns `429 Too Many Requests`
|
||||
- Rate limit headers (`Retry-After`) MUST be included in 429 responses
|
||||
- Configuration stored in `appsettings.json → RateLimiting` section
|
||||
|
||||
## NFR-U0-04: Reliability — Refresh Token Lifetime
|
||||
- Refresh token lifetime: **7 days** (unchanged from current default)
|
||||
- After expiry, the user must re-authenticate via the login page
|
||||
- Refresh token rotation is already implemented — each refresh issues a new token
|
||||
|
||||
## NFR-U0-05: Error Response Format (SECURITY-09, SECURITY-15)
|
||||
- ALL authentication error responses MUST use **RFC 9457 ProblemDetails** format:
|
||||
```json
|
||||
{
|
||||
"type": "https://tools.ietf.org/html/rfc7235#section-3.1",
|
||||
"title": "Unauthorized",
|
||||
"status": 401,
|
||||
"detail": "Invalid credentials."
|
||||
}
|
||||
```
|
||||
- Error messages MUST be generic — do NOT reveal whether email or password was wrong
|
||||
- Error messages MUST NOT expose internal details (stack traces, exception types, DB details)
|
||||
- `asp-problem-details` behavior is already partially handled by `GlobalExceptionHandler`; auth-specific errors may need explicit `ProblemDetails` returns in `AuthController`
|
||||
|
||||
## NFR-U0-06: Maintainability
|
||||
- Rate limiting configuration (window size, request limits) stored in `appsettings.json` — configurable without code changes
|
||||
- CORS origins stored in `appsettings.json` — configurable per environment
|
||||
- No magic strings for cookie name or policy name — use constants
|
||||
|
||||
## NFR-U0-07: Test Coverage
|
||||
- Unit tests for `AuthController` must be updated to cover:
|
||||
- Cookie is set on successful login/refresh
|
||||
- Cookie is cleared on revoke
|
||||
- 401 returned when cookie is missing on refresh
|
||||
- Rate limit behavior (mock rate limiter)
|
||||
- Existing `AuthService` unit tests remain valid (service signature unchanged)
|
||||
Reference in New Issue
Block a user