53 lines
2.7 KiB
Markdown
53 lines
2.7 KiB
Markdown
# Quickstart: Validating Identity and Authentication
|
|||
|
|
|
||
|
|
Prerequisites: migrations applied; `npm run prisma:seed` run so the two demo accounts exist
|
||
|
|
with their new real passwords (documented in the seed script itself, local/dev use only).
|
||
|
|
|
||
|
|
## Scenario 1 — login (User Story 1)
|
||
|
|
|
||
|
|
1. `POST /auth/login` with the seeded admin's correct email/password. **Expected**: `200`, a
|
||
|
|
token, and `{id, email, name, role: 'ADMIN'}`.
|
||
|
|
2. Repeat with the correct email but a wrong password. **Expected**: `401`.
|
||
|
|
3. Repeat with an email that doesn't exist at all. **Expected**: the exact same `401` body/
|
||
|
|
status as step 2 — diff the two responses to confirm they're indistinguishable.
|
||
|
|
|
||
|
|
## Scenario 2 — route gating and role enforcement (User Story 2)
|
||
|
|
|
||
|
|
1. Call an existing admin route (e.g. `POST /admin/teams`) with no `Authorization` header.
|
||
|
|
**Expected**: `401`.
|
||
|
|
2. Repeat with a malformed token (`Bearer not-a-real-token`). **Expected**: `401`.
|
||
|
|
3. Log in as the seeded agent (role `AGENT`); call an admin-only route gated by
|
||
|
|
`requireRole('ADMIN')`. **Expected**: `403`.
|
||
|
|
4. Log in as the seeded admin; repeat step 3's call. **Expected**: `200`/`201` (whatever that
|
||
|
|
route normally returns on success).
|
||
|
|
|
||
|
|
## Scenario 3 — self-identity (User Story 3)
|
||
|
|
|
||
|
|
1. Log in; call `GET /auth/me` with the resulting token. **Expected**: `200`, identity matches
|
||
|
|
the login response exactly.
|
||
|
|
2. Directly deactivate that account (`active: false`) via a direct DB update (simulating an
|
||
|
|
admin action no UI exists for yet); repeat the same `GET /auth/me` call with the same,
|
||
|
|
still-unexpired token. **Expected**: `401` — re-validated against current account state, not
|
||
|
|
the token's own claims.
|
||
|
|
|
||
|
|
## Scenario 4 — admin creates an account (User Story 4)
|
||
|
|
|
||
|
|
1. Log in as admin; `POST /admin/users` with a new email/name/role `AGENT`/password.
|
||
|
|
**Expected**: `201`, response never includes the password or its hash.
|
||
|
|
2. Log in as a non-admin (the seeded agent); repeat step 1. **Expected**: `403`.
|
||
|
|
3. Immediately log in as the newly-created account with the password from step 1. **Expected**:
|
||
|
|
`200` — no manual step needed in between.
|
||
|
|
4. Repeat step 1 with an email already in use. **Expected**: `409`.
|
||
|
|
|
||
|
|
## Scenario 5 — logout (User Story 5)
|
||
|
|
|
||
|
|
1. Log in; call `POST /auth/logout` with the resulting token. **Expected**: `200`.
|
||
|
|
2. Immediately reuse that same token on any gated route. **Expected**: `401` — rejected even
|
||
|
|
though it hasn't naturally expired.
|
||
|
|
|
||
|
|
## What "done" looks like
|
||
|
|
|
||
|
|
All five scenarios pass, and Scenario 2 is additionally verified against at least one
|
||
|
|
already-shipped admin route from each of 002-009 (not just a route this feature itself adds),
|
||
|
|
proving the real gate actually protects what the no-op stub never did.
|