docs: align API reference and data model docs with code reality
API Reference (9 files updated): - Marketplace API: corrected offer endpoints (scoped under /purchase-requests/:id/offers), marked phantom /search /stats /seller/:sellerId /withdraw routes as NOT IMPLEMENTED, documented PUT→PATCH mismatches, removed invalid SellerOffer 'active' status - Dispute API: corrected resolve schema (action enum), categories (no 'fraud'), removed 'under_review' status, added security callouts (3 unguarded endpoints), route shadowing documented, all socket events marked as TODO stubs - Notification API: corrected mark-all-read method+path, fixed broken GET /:id, added unread-count-update event, 90-day TTL documented - Payment API: /create→/save, removed 10+ phantom endpoints, fixed release/refund paths (no /shkeeper/ segment), added 3 unauthenticated endpoint security warnings, stats undercounting documented, export privilege gap documented - Authentication API: 8-digit→6-digit code, no-complexity warning on reset-with-code, rate limiter counts all attempts, passkey stub claims removed, deleteAccount bug noted - Admin API: PUT→PATCH bug documented, wrong status values documented, hard vs soft delete clarified, scanner no-auth security bug, 3 NOT IMPLEMENTED endpoints - Chat API: file upload wrong endpoint bug, archive PUT→PATCH bug, rate limits added - Points API: corrected redeem schema, referral triggers on 'completed' only, leaderboard period ignored, removed 'refund' PointTransaction type - Socket Events: removed request-cancelled, notification-read; added unread-count-update; dispute events all stubs; referral-signup is auth-domain not points-domain Data Models (3 files updated): - SellerOffer: removed 'active' from status enum, withdrawOffer() is dead code - PurchaseRequest: added pending_payment/active statuses, added 'urgent' urgency, corrected description minimum (5 chars), removed finalized/archived - Dispute: corrected action enum, categories (no fraud), removed under_review, security callout on unguarded status/resolve endpoints Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,15 +5,19 @@ tags: [api, auth, reference]
|
||||
|
||||
# Authentication API
|
||||
|
||||
> **Last updated:** 2026-05-29 — aligned with code (see [Doc vs Code Audit Report](../09%20-%20Audits/Doc%20vs%20Code%20Audit%20Report%20-%202026-05-29.md))
|
||||
|
||||
All endpoints are mounted under `/api/auth/*` in `backend/src/app.ts`. The routes file is [`backend/src/services/auth/authRoutes.ts`](../../backend/src/services/auth/authRoutes.ts) and the WebAuthn sub-routes are in [`passkeyRoutes.ts`](../../backend/src/services/auth/passkeyRoutes.ts). Controller logic lives in [`authController.ts`](../../backend/src/services/auth/authController.ts) and [`authService.ts`](../../backend/src/services/auth/authService.ts).
|
||||
|
||||
Two distinct identities are involved: a [[User]] (`models/User.ts`) and a [[TempVerification]] document that holds pending registration data until the email code is confirmed. Tokens are signed JWTs (access + refresh) created in `authService`. See [[Authentication Flow]] for the high-level lifecycle diagram.
|
||||
|
||||
**Token refresh behaviour:** The Axios interceptor handles `401` responses to trigger a token refresh. `403` errors are **not** intercepted and propagate directly to callers.
|
||||
|
||||
## Registration
|
||||
|
||||
### POST /api/auth/register
|
||||
|
||||
**Description:** Start a new registration. Creates a [[TempVerification]] document and emails an 8-digit verification code. The actual [[User]] is only created once the code is verified.
|
||||
**Description:** Start a new registration. Creates a [[TempVerification]] document and emails a **6-digit** verification code. The actual [[User]] is only created once the code is verified.
|
||||
**Auth required:** No
|
||||
**Request body:**
|
||||
```ts
|
||||
@@ -45,7 +49,7 @@ Two distinct identities are involved: a [[User]] (`models/User.ts`) and a [[Temp
|
||||
```ts
|
||||
{
|
||||
email: string;
|
||||
code: string; // 8 digits
|
||||
code: string; // 6 digits (generated by authService.generateVerificationCode())
|
||||
password?: string; // required if not provided at register
|
||||
}
|
||||
```
|
||||
@@ -76,7 +80,7 @@ Two distinct identities are involved: a [[User]] (`models/User.ts`) and a [[Temp
|
||||
|
||||
### POST /api/auth/resend-verification
|
||||
|
||||
**Description:** Re-issues the 8-digit code for a pending or unverified user.
|
||||
**Description:** Re-issues the 6-digit code for a pending or unverified user.
|
||||
**Auth required:** No
|
||||
**Request body:** `{ email: string }`
|
||||
**Response 200:** `{ "success": true, "message": "Verification code resent" }`
|
||||
@@ -116,6 +120,9 @@ Two distinct identities are involved: a [[User]] (`models/User.ts`) and a [[Temp
|
||||
- `401` invalid credentials
|
||||
- `403` email not verified
|
||||
- `423` account locked (after repeated failures, tracked in Redis via `rateLimitService`)
|
||||
|
||||
**⚠️ Rate limiter behaviour:** The attempt counter increments on **every** attempt (before password validation), not only on failures. 5 total attempts within 15 minutes triggers lockout — a user burning 5 attempts with typos will be locked out even if they never had a valid password.
|
||||
|
||||
**Side effects:**
|
||||
- Updates `user.lastLoginAt`.
|
||||
- Pushes refresh token onto `user.refreshTokens`.
|
||||
@@ -194,7 +201,9 @@ Two distinct identities are involved: a [[User]] (`models/User.ts`) and a [[Temp
|
||||
|
||||
## Passkey / WebAuthn
|
||||
|
||||
Routes are nested under `/api/auth/` via `passkeyRoutes`. Service: `passkeyService.ts`.
|
||||
Routes are nested under `/api/auth/` via `passkeyRoutes`. Service: `passkeyService.ts`. These routes go directly to the Express backend via the `next.config.ts` rewrite rule (`/api/:path*` → backend). No Next.js route handlers exist for passkey paths.
|
||||
|
||||
**Implementation status:** Passkey attestation is **fully implemented** using `@simplewebauthn/server`. The registration and authentication flows are production-ready.
|
||||
|
||||
### POST /api/auth/passkey/authenticate/challenge
|
||||
|
||||
@@ -247,7 +256,7 @@ Routes are nested under `/api/auth/` via `passkeyRoutes`. Service: `passkeyServi
|
||||
|
||||
### POST /api/auth/reset-password
|
||||
|
||||
**Description:** Sets a new password using a token from the reset email. Wipes refresh tokens.
|
||||
**Description:** Sets a new password using a token from the reset email. Wipes refresh tokens. Enforces password complexity via `passwordResetValidation`.
|
||||
**Auth required:** No
|
||||
**Request body:**
|
||||
```ts
|
||||
@@ -261,10 +270,11 @@ Routes are nested under `/api/auth/` via `passkeyRoutes`. Service: `passkeyServi
|
||||
|
||||
### POST /api/auth/reset-password-with-code
|
||||
|
||||
**Description:** Alternative reset flow using a numeric code instead of a tokenised URL.
|
||||
**Description:** Alternative reset flow using a **6-digit** numeric code instead of a tokenised URL.
|
||||
**Auth required:** No
|
||||
**Request body:** `{ email, code, password }`
|
||||
**Response 200:** `{ "success": true }`
|
||||
**⚠️ No password complexity validation:** Unlike `POST /api/auth/reset-password` (token-based), this endpoint does **not** run `passwordResetValidation`. Any non-empty password will be accepted without complexity checks.
|
||||
|
||||
### POST /api/auth/change-password
|
||||
|
||||
@@ -280,6 +290,7 @@ Routes are nested under `/api/auth/` via `passkeyRoutes`. Service: `passkeyServi
|
||||
**Response 200:** `{ "success": true, "message": "Password updated" }`
|
||||
**Errors:** `400` validation, `401` wrong current password.
|
||||
**Side effects:** Clears `user.refreshTokens` (forces re-login on other devices).
|
||||
**⚠️ No frontend UI:** This endpoint exists and is functional in the backend, but no frontend page currently exposes a change-password form. It can only be called directly.
|
||||
|
||||
## Current user / profile
|
||||
|
||||
@@ -316,13 +327,15 @@ Routes are nested under `/api/auth/` via `passkeyRoutes`. Service: `passkeyServi
|
||||
|
||||
### DELETE /api/auth/account
|
||||
|
||||
**Description:** Permanently deletes the caller's account after re-authenticating with password.
|
||||
**Description:** Permanently deletes the caller's account after re-authenticating with password. Requires `{ password }` in the request body and runs `deleteAccountValidation`.
|
||||
**Auth required:** Bearer JWT
|
||||
**Request body:** `{ password: string }`
|
||||
**Response 200:** `{ "success": true, "message": "Account deleted" }`
|
||||
**Errors:** `401` bad password.
|
||||
**Side effects:** Removes [[User]] document, clears Redis session, cascades configured by `dataCleanupService`.
|
||||
|
||||
**⚠️ KNOWN BUG — Frontend calls wrong endpoint:** The frontend currently calls `DELETE /user/profile` instead of `DELETE /api/auth/account`. Account deletion initiated from the frontend UI will fail or hit the wrong handler.
|
||||
|
||||
## Error codes summary
|
||||
|
||||
| HTTP | App code | Meaning |
|
||||
|
||||
Reference in New Issue
Block a user