# EasyStream API Authentication Guide ## Overview EasyStream now supports modern JWT token-based authentication for API clients, alongside traditional session-based authentication for web pages. ## Authentication Systems ### 1. **Session-Based Authentication** (Traditional Web Pages) - Uses PHP sessions with cookies - Managed by `VAuth::login()` and `VAuth::logout()` - Stored in `db_sessions` table - Best for: Traditional server-rendered pages ### 2. **JWT Token Authentication** (Modern APIs) - Uses Bearer tokens in Authorization header - Managed by `VAuth::loginWithToken()` and `VAuth::validateJWTToken()` - Stateless (no server-side session storage) - Best for: SPAs, mobile apps, API clients --- ## Backend API Endpoints ### Base URL ``` http://localhost:8083/api ``` ### Authentication Endpoints #### 1. **Login with Token** (New) Get a JWT token for API authentication. **Endpoint:** `POST /auth.php?action=login_token` **Request Body:** ```json { "identifier": "username or email", "password": "your_password", "expires_in": 86400 // Optional: token expiry in seconds (default: 24 hours) } ``` **Response (Success):** ```json { "success": true, "message": "Login successful", "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "Bearer", "expires_in": 86400, "user": { "user_id": 1, "username": "john_doe", "email": "john@example.com", "role": "member" } } ``` **Response (Error):** ```json { "success": false, "message": "Invalid credentials" } ``` --- #### 2. **Verify Token** Validate a JWT token and get user information. **Endpoint:** `GET /auth.php?action=verify_token` or `POST /auth.php?action=verify_token` **Authorization Header:** ``` Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ``` **Alternative (POST body):** ```json { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." } ``` **Response (Success):** ```json { "success": true, "valid": true, "user": { "user_id": 1, "username": "john_doe", "email": "john@example.com", "role": "member" } } ``` --- #### 3. **Traditional Login** (Session-based) For web pages that need PHP session authentication. **Endpoint:** `POST /auth.php?action=login` **Request Body:** ```json { "identifier": "username or email", "password": "your_password", "remember_me": false } ``` **Response:** ```json { "success": true, "message": "Login successful", "user": { ... } } ``` *Note: This sets a PHP session cookie, not a JWT token.* --- ## Frontend API Helper Usage ### Include the API Helper Add to your HTML: ```html ``` ### Initialize API Client ```javascript // API client is automatically initialized as window.api const api = window.api; // or new EasyStreamAPI() ``` ### Authentication Examples #### Login and Get Token ```javascript try { const result = await api.login('john_doe', 'password123'); if (result.success) { console.log('Logged in!', result.user); console.log('Token:', result.token); // Token is automatically stored in localStorage } } catch (error) { console.error('Login failed:', error.message); } ``` #### Check Authentication Status ```javascript if (api.isAuthenticated()) { console.log('User is authenticated'); } else { console.log('User is not authenticated'); } ``` #### Get Current User Info ```javascript try { const userData = await api.getCurrentUser(); console.log('Current user:', userData.user); } catch (error) { console.error('Not authenticated:', error); } ``` #### Logout ```javascript try { await api.logout(); console.log('Logged out successfully'); } catch (error) { console.error('Logout error:', error); } ``` --- ### Making Authenticated API Requests The API helper automatically includes the Bearer token in all requests. #### GET Request ```javascript try { const videos = await api.get('/videos.php', { page: 1, limit: 20, sort: 'newest' }); console.log('Videos:', videos); } catch (error) { console.error('Error:', error); } ``` #### POST Request ```javascript try { const newVideo = await api.post('/videos.php', { title: 'My Awesome Video', description: 'Check this out!', privacy: 'public' }); console.log('Video created:', newVideo); } catch (error) { console.error('Error:', error); } ``` #### PUT Request ```javascript try { const updated = await api.put('/videos.php?id=123', { title: 'Updated Title' }); console.log('Video updated:', updated); } catch (error) { console.error('Error:', error); } ``` #### DELETE Request ```javascript try { const result = await api.delete('/videos.php?id=123'); console.log('Video deleted:', result); } catch (error) { console.error('Error:', error); } ``` --- ## Manual Fetch Example (Without Helper) If you prefer to use fetch() directly: ```javascript // Login and get token const loginResponse = await fetch('/api/auth.php?action=login_token', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ identifier: 'john_doe', password: 'password123' }) }); const loginData = await loginResponse.json(); const token = loginData.token; // Store token localStorage.setItem('jwt_token', token); // Make authenticated request const response = await fetch('/api/videos.php', { method: 'GET', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }); const videos = await response.json(); ``` --- ## cURL Examples ### Login with Token ```bash curl -X POST http://localhost:8083/api/auth.php?action=login_token \ -H "Content-Type: application/json" \ -d '{ "identifier": "john_doe", "password": "password123" }' ``` ### Verify Token ```bash curl -X GET http://localhost:8083/api/auth.php?action=verify_token \ -H "Authorization: Bearer YOUR_JWT_TOKEN_HERE" ``` ### Authenticated API Request ```bash curl -X GET http://localhost:8083/api/videos.php?page=1&limit=10 \ -H "Authorization: Bearer YOUR_JWT_TOKEN_HERE" ``` --- ## Token Management ### Token Storage - Frontend: Stored in `localStorage` with expiry time - Backend: JWT is stateless (no server-side storage) ### Token Expiry - Default: 24 hours (86400 seconds) - Configurable via `JWT_EXPIRY` in `.env` - Client automatically clears expired tokens ### Token Security - Secret: Stored in `JWT_SECRET` environment variable - Algorithm: HS256 (HMAC-SHA256) - Validation: Signature verified on every request --- ## Migration Guide ### For Existing AJAX Code **Before (jQuery with sessions):** ```javascript $.post('/some_endpoint.php', { action: 'do_something' }, function(data) { console.log(data); }); ``` **After (Fetch with JWT):** ```javascript api.post('/some_endpoint.php', { action: 'do_something' }) .then(data => console.log(data)) .catch(error => console.error(error)); ``` --- ## Environment Configuration Update your `.env` file: ```env # JWT Configuration JWT_SECRET=9a652ee880c41bafb0a81d38d54b029d63903eeaafccaa8c12880a913931f63b JWT_EXPIRY=86400 # CORS Configuration (for separate frontends) CORS_ORIGIN=http://localhost:3000 ``` --- ## Error Handling ### Common Errors #### 401 Unauthorized ```json { "success": false, "message": "Invalid or expired token" } ``` **Solution:** Re-login to get a new token. #### 403 Forbidden ```json { "success": false, "message": "Access denied" } ``` **Solution:** User doesn't have permission for this resource. #### 429 Rate Limited ```json { "success": false, "message": "Too many requests" } ``` **Solution:** Wait before retrying. --- ## Best Practices 1. **Always use HTTPS in production** - JWT tokens should be transmitted over secure connections 2. **Store tokens securely** - Use localStorage for web, secure storage for mobile 3. **Handle token expiry** - Implement token refresh or re-login flow 4. **Validate on every request** - Backend validates tokens on all protected endpoints 5. **Clear tokens on logout** - Remove tokens from storage when user logs out 6. **Use CORS properly** - Configure `Access-Control-Allow-Origin` for your frontend domain --- ## Support For issues or questions, check: - EasyStream documentation: `/docs/` - API logs: `f_data/logs/` - Error handling: `VLogger` and `VErrorHandler` classes