Frontend API Client
Axios-based API client with session management, automatic token refresh, and centralized error handling.
Frontend API Client
The SLMS frontend uses two API client layers, each serving a different purpose.
1. Session API Client (NextAuth Integration)
File: src/lib/api.ts
This is the primary API client used by all page-level data fetching. It integrates with NextAuth's session management to automatically attach JWT tokens.
Request Interceptor
API Call
│
▼
getSession() ← Retrieves the current NextAuth session
│
▼
Attach Authorization: Bearer <accessToken>
│
▼
Send RequestEvery request automatically retrieves the current session and attaches the accessToken to the Authorization header.
Response Interceptor
- 401 Unauthorized: Calls
signOut({ callbackUrl: '/login' })to force re-authentication - All errors: Extracts
errorormessagefrom the response body and displays a Sonner toast with deduplication (using the error message as the toast ID)
Usage
import api from '@/lib/api';
// All requests automatically include the JWT
const { data } = await api.get('/books');
const { data } = await api.post('/books', bookData);2. Enterprise API Client (Notification Manager Integration)
File: src/services/api/client.ts
This is the new enterprise-grade client designed for the centralized feedback system. It connects directly to the Error Code Registry and Notification Manager.
Key Differences from lib/api.ts
| Feature | lib/api.ts | services/api/client.ts |
|---|---|---|
| Auth | NextAuth getSession() | Direct Bearer token |
| Token Refresh | Handled by NextAuth | Built-in silent refresh with request queuing |
| Error Handling | Generic toast | Error Code Registry → Notification Manager |
| Validation Errors | Generic toast | Passed through for inline React Hook Form handling |
| Network Errors | Toast | Global Banner |
Token Refresh Flow
Request → 401 Response
│
├── Is another refresh in progress?
│ ├── Yes → Queue this request (Promise)
│ └── No → Set isRefreshing = true
│
▼
POST /auth/refresh (with cookies)
│
├── Success → Replay all queued requests
│ Reset isRefreshing = false
│
└── Failure → Toast: "Session expired"
Redirect to /login
Reject all queued requestsError Routing
// Validation errors → NOT toasted (handled by forms inline)
if (code === 'VALIDATION_FAILED') return Promise.reject(error);
// Other errors → Routed through Error Code Registry
const errorDetail = ERROR_CODES[code] || ERROR_CODES.DEFAULT;
if (errorDetail.severity === 'error') notification.error(errorDetail.message);
if (errorDetail.severity === 'warning') notification.warning(errorDetail.message);NextAuth Configuration
Auth Config (src/auth.config.ts)
- Session strategy: JWT (stateless)
- Session max age: 15 minutes
- Token refresh: Automatic in the
jwtcallback whenaccessTokenExpiresis past
Auth Provider (src/auth.ts)
- Provider: Credentials (email/rollNumber + password)
- Backend call:
POST /api/v1/auth/login - Rate limiting: Client-side rate limit (5 requests/minute per IP) as defense-in-depth
- Returned user object:
{ id, role, email, rollNumber, contactNumber, name, accessToken, refreshToken }
Middleware (src/middleware.ts)
Edge middleware enforcing route-level RBAC:
| Path Prefix | Required Role |
|---|---|
/admin/* | ROLE_ADMIN |
/librarian/* | ROLE_ADMIN or ROLE_LIBRARIAN |
/staff/* | ROLE_STAFF |
/student/* | ROLE_STUDENT |
/login, /register | Redirects to dashboard if already authenticated |
Environment Variables
| Variable | Where | Purpose |
|---|---|---|
NEXT_PUBLIC_API_URL | Client + Server | Backend API base URL |
API_URL | Server only | Backend URL for SSR calls |
AUTH_SECRET | Server only | NextAuth JWT signing secret |
NEXTAUTH_URL | Server only | Canonical URL for NextAuth |
AUTH_TRUST_HOST | Server only | Trust the host header (required for proxied environments) |