| # Testing the Authentication System Locally | |
| ## Prerequisites | |
| You need both: | |
| 1. **Next.js Frontend** (this project) - port 3000 | |
| 2. **FastAPI Backend** - port 8000 (or configured URL) | |
| The backend must have: | |
| - `POST /admin/login` endpoint | |
| - `GET /admin/me` endpoint | |
| ## Quick Start | |
| ### 1. Configure Backend URL | |
| Edit `.env.local`: | |
| ```env | |
| # For local backend | |
| NEXT_PUBLIC_API_URL=http://localhost:8000 | |
| # Or your backend URL | |
| NEXT_PUBLIC_API_URL=https://your-backend-url.com | |
| ``` | |
| ### 2. Start the Frontend | |
| ```bash | |
| npm run dev | |
| ``` | |
| Should see: | |
| ``` | |
| β² Next.js 16.1.6 | |
| - Local: http://localhost:3000 | |
| ... | |
| ready - started server and apps | |
| ``` | |
| ### 3. Try Login | |
| Open browser: http://localhost:3000 | |
| Should redirect to: http://localhost:3000/login | |
| ## Test Cases | |
| ### Test 1: Authentication Required | |
| **Step 1:** Clear browser cookies | |
| - DevTools β Application β Cookies β Delete `auth_token` | |
| **Step 2:** Try accessing `/recruitment` | |
| - URL: http://localhost:3000/recruitment | |
| - Should redirect to `/login` | |
| **Result:** β Pass if redirected to login page | |
| --- | |
| ### Test 2: Successful Login | |
| **Step 1:** Go to login page | |
| - URL: http://localhost:3000/login | |
| **Step 2:** Enter credentials | |
| - Username: `admin` (or your test user) | |
| - Password: Your test password | |
| **Step 3:** Click "Sign In" | |
| **Expected:** | |
| - Form shows loading spinner | |
| - Redirects to `/recruitment` on success | |
| **Check Success:** | |
| - DevTools β Application β Cookies | |
| - Should see `auth_token` cookie with httpOnly flag β | |
| - Cookie value should NOT be visible (httpOnly protection) | |
| **Result:** β Pass if redirected and cookie set | |
| --- | |
| ### Test 3: Session Persistence | |
| **Step 1:** After successful login, reload page | |
| - Press F5 or Ctrl+R | |
| **Expected:** | |
| - Page stays on `/recruitment` | |
| - User info still visible in header | |
| **Check:** | |
| - DevTools β Application β Cookies | |
| - `auth_token` should still exist | |
| - Header shows user name and role | |
| **Result:** β Pass if session persists across reload | |
| --- | |
| ### Test 4: Cookie Security | |
| **Step 1:** After login, open DevTools | |
| - F12 β Application β Cookies | |
| **Step 2:** Check `auth_token` properties | |
| **Expected:** | |
| ``` | |
| Name: auth_token | |
| Value: [cannot see due to httpOnly] | |
| Domain: localhost | |
| Path: / | |
| Expires: 7 days from now | |
| HttpOnly: β (checked) | |
| Secure: β (not in dev, β in prod) | |
| SameSite: Lax | |
| ``` | |
| **Result:** β Pass if httpOnly is checked | |
| --- | |
| ### Test 5: Token Not in JavaScript | |
| **Step 1:** After login, open DevTools Console | |
| - F12 β Console | |
| **Step 2:** Try accessing token from JavaScript | |
| ```javascript | |
| document.cookie | |
| // Should NOT show auth_token (httpOnly protection) | |
| localStorage.getItem('auth_token') | |
| // Should return null (we don't store in localStorage) | |
| sessionStorage.getItem('auth_token') | |
| // Should return null (we don't store in sessionStorage) | |
| ``` | |
| **Expected:** | |
| - All return empty or null | |
| - Token is completely inaccessible to JavaScript | |
| **Result:** β Pass if no token visible to JS | |
| --- | |
| ### Test 6: Logout | |
| **Step 1:** Click logout button | |
| - Header β User dropdown β Logout | |
| **Step 2:** Observe behavior | |
| **Expected:** | |
| - Redirects to `/login` page | |
| - Cookie deleted (disappears from DevTools) | |
| - Can't access `/recruitment` anymore | |
| **Check:** | |
| - DevTools β Cookies | |
| - `auth_token` should be gone | |
| - Try accessing `/recruitment` β redirected to `/login` | |
| **Result:** β Pass if redirected and cookie cleared | |
| --- | |
| ### Test 7: Invalid Credentials | |
| **Step 1:** Go to `/login` page | |
| **Step 2:** Enter wrong password | |
| - Username: `admin` | |
| - Password: `wrongpassword` | |
| **Step 3:** Click "Sign In" | |
| **Expected:** | |
| - Form shows error message | |
| - Does NOT redirect | |
| - Shows Something like "Invalid credentials" | |
| **Check:** | |
| - DevTools β Network β `/api/auth/login` request | |
| - Response status should be 401 | |
| **Result:** β Pass if error shown and no redirect | |
| --- | |
| ### Test 8: Form Validation | |
| **Step 1:** Go to `/login` page | |
| **Step 2:** Try submitting empty form | |
| - Click "Sign In" without entering anything | |
| **Expected:** | |
| - "Username is required" error | |
| - "Password is required" error | |
| - Form does NOT submit | |
| **Step 3:** Enter short password (less than 6 chars) | |
| - Username: `admin` | |
| - Password: `pass` | |
| **Expected:** | |
| - "Password must be at least 6 characters" error | |
| **Result:** β Pass if validation works | |
| --- | |
| ### Test 9: User Info Display | |
| **Step 1:** Login successfully | |
| **Step 2:** Check header | |
| - Look at top-right corner | |
| **Expected:** | |
| - Shows user avatar (initials in circle) | |
| - Shows full username | |
| - Shows user role | |
| **Check:** | |
| - Avatar color should match gradient | |
| - Click dropdown shows "Logout" option | |
| **Result:** β Pass if user info displayed | |
| --- | |
| ### Test 10: Role-Based Access | |
| **Step 1:** Check `/admin/me` response | |
| - DevTools β Network β Find request to `/api/auth/me` | |
| - Look at response body | |
| **Expected Response:** | |
| ```json | |
| { | |
| "user_id": "...", | |
| "username": "admin", | |
| "role": "admin", | |
| "tenant_id": "...", | |
| ... | |
| } | |
| ``` | |
| **Step 2:** Verify role in AuthContext | |
| - Open DevTools β Console | |
| - Run: `const { useAuth } = require('@/lib/auth-context'); console.log(user.role)` | |
| - Or just check header displays correct role | |
| **Result:** β Pass if role is correctly retrieved from backend | |
| --- | |
| ## Troubleshooting | |
| ### Problem: "Could not connect to backend" | |
| **Symptoms:** | |
| - Error after entering credentials | |
| - Network tab shows failed request to `/admin/login` | |
| - Error message like "Failed to connect" | |
| **Solution:** | |
| 1. Check backend is running (`python main.py` or `fastapi run`) | |
| 2. Check backend URL in `.env.local` | |
| 3. Check CORS headers if on different domain | |
| 4. Try accessing backend directly: `curl http://localhost:8000/docs` | |
| --- | |
| ### Problem: "Stays on login after entering correct credentials" | |
| **Symptoms:** | |
| - Form submits but doesn't redirect | |
| - No error message | |
| **Solution:** | |
| 1. Check DevTools β Network tab | |
| 2. Look at `/api/auth/login` request/response | |
| 3. Check response status (should be 200) | |
| 4. Check response body has user data | |
| 5. Verify backend `/admin/me` returns correct format | |
| --- | |
| ### Problem: "Cookie not being set" | |
| **Symptoms:** | |
| - Login redirects but `auth_token` cookie missing | |
| - Reload page β back to login | |
| **Solution:** | |
| 1. Check `/api/auth/login` response includes `Set-Cookie` header | |
| 2. Check response status is 200 | |
| 3. Verify cookie name is `auth_token` (case-sensitive) | |
| 4. For development, remove `secure: true` requirement | |
| 5. Check browser cookie settings allow cookies | |
| --- | |
| ### Problem: "User info not showing in header" | |
| **Symptoms:** | |
| - Header shows "Loading..." or "?" | |
| - User role shows as empty | |
| **Solution:** | |
| 1. Check DevTools β Network β `/api/auth/me` response | |
| 2. Verify response includes `full_name`, `role`, `username` | |
| 3. Check `/admin/me` endpoint returns these fields | |
| 4. Check user context logs: `console.log(user)` | |
| 5. Wait for initial auth load (might be loading state) | |
| --- | |
| ### Problem: "Can't logout" | |
| **Symptoms:** | |
| - Clicking logout does nothing | |
| - Or shows error | |
| **Solution:** | |
| 1. Check DevTools β Network β `/api/auth/logout` response | |
| 2. Should be 200 status | |
| 3. Check cookie gets deleted manually | |
| 4. Try hard refresh after logout | |
| 5. Clear cookies manually and try again | |
| --- | |
| ## Advanced Testing | |
| ### Testing with curl | |
| **Test login endpoint directly:** | |
| ```bash | |
| curl -X POST http://localhost:8000/admin/login \ | |
| -H "Content-Type: application/x-www-form-urlencoded" \ | |
| -d "username=admin&password=yourpassword" \ | |
| -v | |
| ``` | |
| Should return: | |
| ``` | |
| { | |
| "access_token": "eyJ...", | |
| "token_type": "bearer" | |
| } | |
| ``` | |
| **Test /admin/me endpoint:** | |
| ```bash | |
| curl http://localhost:8000/admin/me \ | |
| -H "Authorization: Bearer <your_token>" \ | |
| -v | |
| ``` | |
| Should return user object with role, tenant_id, etc. | |
| --- | |
| ### Testing with Postman | |
| 1. **Create POST request to `/api/auth/login`** | |
| - Method: POST | |
| - URL: http://localhost:3000/api/auth/login | |
| - Body (JSON): | |
| ```json | |
| { | |
| "username": "admin", | |
| "password": "yourpassword" | |
| } | |
| ``` | |
| - Send | |
| - Check cookie in response headers | |
| 2. **Get user with token cookie** | |
| - Method: GET | |
| - URL: http://localhost:3000/api/auth/me | |
| - Cookies: `auth_token=<value_from_previous_response>` | |
| - Send | |
| - Should return user object | |
| --- | |
| ## Performance Testing | |
| ### Check Auth Performance | |
| **Time to login:** | |
| 1. Start timer when clicking "Sign In" | |
| 2. Stop timer when redirected to `/recruitment` | |
| 3. Should be < 2 seconds (typical: 0.5-1 second) | |
| **Time to load protected page:** | |
| 1. After login, reload page | |
| 2. Check time until content appears | |
| 3. Should be < 1 second (cached session) | |
| --- | |
| ## Checklist - All Tests Passed β | |
| - [ ] Can access `/login` without auth | |
| - [ ] Can't access `/recruitment` without auth (redirects to login) | |
| - [ ] Successful login redirects to `/recruitment` | |
| - [ ] Session persists across page reloads | |
| - [ ] Auth token cookie is httpOnly | |
| - [ ] Auth token NOT accessible via JavaScript | |
| - [ ] Logout clears cookie and redirects to `/login` | |
| - [ ] Invalid credentials show error | |
| - [ ] Form validation works (required fields, min length) | |
| - [ ] User info displays in header | |
| - [ ] User role displays correctly | |
| If all β , your authentication system is ready for production! | |
| --- | |
| ## Production Checklist | |
| Before deploying to production: | |
| - [ ] HTTPS enabled (secure: true in cookies) | |
| - [ ] Backend CORS configured for frontend domain | |
| - [ ] Rate limiting on login endpoint | |
| - [ ] Database backups configured | |
| - [ ] Error logging set up (Sentry, LogRocket, etc.) | |
| - [ ] Monitoring alerts for auth failures | |
| - [ ] Session timeout configured | |
| - [ ] Password policy enforced | |
| - [ ] Multi-tenant isolation verified | |
| - [ ] Load testing performed (concurrent logins) | |
| --- | |
| ## Need Help? | |
| - Check `AUTH_IMPLEMENTATION.md` for detailed docs | |
| - Check `AUTH_QUICK_REFERENCE.md` for code examples | |
| - Review logs in vs code terminal for errors | |
| - Check browser DevTools for request/response details | |
| - Verify backend endpoints match specification | |