# `AuthController` plan ## Scope - **Controller**: `app/Http/Controllers/Api/Auth/AuthController.php` - **Purpose**: JWT login, token refresh, current-user lookup, logout. - **Primary dependencies**: - `App\Services\Auth\ApiLoginSecurityService` (rate limiting / IP blocking, attempt tracking, response builder) - `PHPOpenSourceSaver\JWTAuth\Facades\JWTAuth` (token issuance/refresh/invalidation) - `Illuminate\Support\Facades\Auth` (current user) ## Routes - **Public (no `/v1`)** - `POST /api/login` → `login` - **Versioned (`/v1`)** - `POST /api/v1/login` → `login` - **Auth prefix (`/v1/auth`)** - `POST /api/v1/auth/login` → `login` - `POST /api/v1/auth/refresh` → `refresh` (middleware: `jwt.auth`) - `POST /api/v1/auth/logout` → `logout` (middleware: `auth:api`) - `GET /api/v1/auth/me` → `me` (middleware: `auth:api`) ## Authentication & authorization - **`login`**: public; checks credentials, then issues JWT. - **`refresh`**: requires a valid JWT via `jwt.auth`. - **`me`/`logout`**: require `auth:api` (JWT/guarded user). ## Request/validation expectations - **`login`**: - Accepts JSON or form payload. Extracts `email`, `password`. - Returns `400` if missing. - Normalizes email to lowercase; looks up `User` by case-insensitive email. - **`refresh`**: - Expects bearer token in request (handled by `JWTAuth::parseToken()`). - **`logout`**: - Attempts JWT invalidation when bearer token looks like a JWT (3 dot-separated segments). - Also deletes `currentAccessToken()` when supported (supports Sanctum-style tokens if present). ## Response shapes - **`login` success**: `ApiLoginSecurityService::buildLoginResponse($user, $jwtToken)` (treat as canonical shape). - **`login` failures**: - `400`: `{ status:false, message:"Email and password are required." }` - `401`: `{ status:false, message:"Invalid email or password." }` - `403`: `{ status:false, message:"Account suspended. Please reset your password." }` - `429`: `{ status:false, message:"Too many failed attempts..." }` - **`refresh` success** (Base API shape): - `{ status:true, message:"Token refreshed.", data:{ access_token, token_type:"bearer", expires_in } }` - **`me` success** (Base API shape): - `{ status:true, message:"OK", data:{ id, firstname, lastname, email, class_section_id, class_section_name } }` - **`logout` success** (Base API shape): - `{ status:true, message:"Logged out.", data:null }` ## Side effects & security notes - Logs IP attempt / failed attempt / successful login via `ApiLoginSecurityService`. - Suspended users are rejected **after** verifying credentials (avoids email enumeration by response shape). ## Error handling expectations - `refresh`: any exception becomes `401` via `respondError('Token refresh failed.', 401)`. - `logout`: JWT invalidation errors are intentionally ignored. ## Test plan (feature) - **Login** - Missing email/password → `400`. - Unknown email → `401` and IP attempt logged. - Wrong password → `401` and failed attempt handling invoked. - Suspended user with correct password → `403`. - Successful login returns expected response shape and includes token. - IP blocked → `429`. - **Refresh** - Valid token refresh returns new token + expires_in. - Invalid/missing token returns `401`. - **Me/Logout** - Requires auth; returns `401` unauthenticated. - Logout returns success even if token invalidation fails.