# ZUMRI Authentication API All endpoints are available under both `/api/auth` and `/api/v1/auth`; new clients should use `/api/v1`. JSON errors use the Phase 0 standard error envelope. Examples contain placeholders only. ## Account states - `PENDING_VERIFICATION`: registration exists but password/OAuth session creation is denied. - `ACTIVE`: authentication and refresh are permitted. - `SUSPENDED` and `DEACTIVATED`: login, refresh, and access-token middleware are denied. ## Register a customer `POST /api/v1/auth/register` ```json {"firstName":"Asha","lastName":"Perera","email":"asha@example.com","password":"Strong!1234x","phoneNumber":"+94000000000","address":"Customer-provided value"} ``` Public registration always creates `customer`; supplied privileged account fields are rejected/stripped by strict validation. Business and privileged registration are not public Phase 1 flows. ## Verify or resend email verification - `POST /api/v1/auth/verify-email` — `{"token":"verification-token-from-email"}` - `POST /api/v1/auth/resend-verification` — `{"email":"asha@example.com"}` Tokens are random, stored only by hash in Redis, expire, and are single-use. Resend invalidates the previous token. Resend returns a generic response. ## Password plus OTP login `POST /api/v1/auth/login` ```json {"email":"asha@example.com","password":"Strong!1234x","rememberMe":true,"clientType":"WEB","deviceName":"Personal laptop"} ``` Successful credential verification returns HTTP 202 and a `challengeId`; it does not create a session. A hashed six-digit OTP challenge is stored in Redis for the configured TTL and attempt limit. `POST /api/v1/auth/verify-otp` ```json {"challengeId":"00000000-0000-4000-8000-000000000000","otp":"000000","clientType":"WEB"} ``` Successful verification consumes the challenge, creates a durable session, and issues tokens. `POST /api/v1/auth/req-otp` remains an alias for login challenge creation. The historical endpoint that submitted email+OTP to `/login` is intentionally superseded by challenge IDs. ## Token transport `clientType: WEB` sets `access_token` and `refresh_token` as HttpOnly cookies. Production cookies use `Secure` and `SameSite=None` for the intended cross-subdomain frontend/API deployment. The refresh cookie is restricted to `/api`. The response includes the access token for current compatibility but never includes the web refresh token. `clientType: MOBILE` returns access and refresh tokens in JSON and does not depend on cookies. Mobile clients must store the refresh token in operating-system secure storage. Access tokens remain short-lived regardless of Remember Me. ## Refresh and rotation `POST /api/v1/auth/refresh` Web request body may be `{}`; mobile sends `{"clientType":"MOBILE","refreshToken":"opaque-token"}`. Every successful call revokes/replaces the previous session row and returns a new token pair. Replaying a rotated token revokes its entire token family. Only SHA-256 refresh hashes are persisted. ## Current identity `GET /api/v1/auth/me` requires the access cookie or `Authorization: Bearer `. It returns identity fields, account state, verification status, profile, and effective permissions. It omits password, token version, session hashes, and OAuth internals. ## Logout - `POST /api/v1/auth/logout` revokes the session identified by refresh or access token and is idempotent. - `POST /api/v1/auth/logout-all` requires authentication, increments `tokenVersion`, revokes every active session, and clears cookies. ## Password recovery and change - `POST /api/v1/auth/forgot-password` — `{"email":"asha@example.com"}`; response is generic. - `POST /api/v1/auth/reset-password` — token, `newPassword`, `confirmPassword`. - `POST /api/v1/auth/change-password` — authenticated; `currentPassword`, `newPassword`, `confirmPassword`. Reset tokens are random, hash-only Redis records and atomically consumed. Reset/change enforce the same password policy, increment token version, and revoke all sessions. The user must log in again. ## Google and Apple - `POST /api/v1/auth/google` - `POST /api/v1/auth/apple` ```json {"idToken":"provider-signed-id-token","rememberMe":false,"clientType":"WEB"} ``` Google verification validates signature/audience/issuer/expiry through Google's verifier and requires verified email. Apple validates the provider JWKS signature, issuer, audience, expiry, and stable subject. Identities persist `(provider, provider_subject)` uniquely; provider tokens are discarded. Verified email auto-linking is permitted only for customer accounts. Privileged and rider accounts are never automatically linked by email. ## Administrative and rider compatibility - `POST /api/v1/admin/auth/login` and `/verify-otp` use the shared challenge/session flow but only accept privileged account types. - `POST /api/v1/rider/auth/login` and `/verify-otp` use the same system and only accept rider accounts. No separate token implementation exists for these actors. ## Password policy Minimum 12 characters with uppercase, lowercase, a symbol, and at least four numeric characters. Registration, reset, and change use the same Zod schema.