38 lines
2.0 KiB
Markdown
38 lines
2.0 KiB
Markdown
# Quickstart: Validating Authentication Hardening
|
|||
|
|
|
||
|
|
## Scenario 1 — password reset, end to end
|
||
|
|
|
||
|
|
1. `POST /auth/password-reset/request` with a real seeded account's email. **Expected**: `200`,
|
||
|
|
generic message; the server log shows a `password_reset_requested` line with a `resetUrl`
|
||
|
|
containing the real token.
|
||
|
|
2. Repeat with an email that doesn't exist. **Expected**: identical `200` response body to
|
||
|
|
step 1 — diff them to confirm.
|
||
|
|
3. `POST /auth/password-reset/consume` with the token from step 1's log and a policy-meeting new
|
||
|
|
password. **Expected**: `200`.
|
||
|
|
4. Repeat step 3 with the same token. **Expected**: rejected — the token is single-use.
|
||
|
|
5. `POST /auth/login` with the account's email and the new password from step 3. **Expected**:
|
||
|
|
`200`. Repeat with the account's old password. **Expected**: `401`.
|
||
|
|
|
||
|
|
## Scenario 2 — password strength enforced everywhere
|
||
|
|
|
||
|
|
1. `POST /admin/users` (as admin) with a password shorter than `PASSWORD_MIN_LENGTH`.
|
||
|
|
**Expected**: `400`, naming the actual minimum length.
|
||
|
|
2. `POST /auth/password-reset/consume` with a valid token and a too-short new password.
|
||
|
|
**Expected**: the same `400` rejection reason as step 1.
|
||
|
|
|
||
|
|
## Scenario 3 — login rate limiting
|
||
|
|
|
||
|
|
1. Submit `LOGIN_RATE_LIMIT_MAX_ATTEMPTS` failed login attempts for the same email within
|
||
|
|
`LOGIN_RATE_LIMIT_WINDOW_SECONDS`. **Expected**: each returns `401` (the existing
|
||
|
|
identical-failure-response).
|
||
|
|
2. Submit one more attempt for that same email, still within the window — this time with the
|
||
|
|
*correct* password. **Expected**: `429`, not `200` — the rate limit is checked before
|
||
|
|
credentials (FR-007).
|
||
|
|
3. Submit an attempt for a *different* email within the same window. **Expected**: proceeds
|
||
|
|
normally (evaluated on its own credentials, not rate-limited).
|
||
|
|
|
||
|
|
## What "done" looks like
|
||
|
|
|
||
|
|
All three scenarios pass against a real Postgres/Redis, and `POST /admin/users`'s own existing
|
||
|
|
tests (010-identity-auth) still pass with the added password-strength check in place.
|