# `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.

