Sync current dev state
Some checks failed
EasyStream Test Suite / test (pull_request) Has been cancelled
EasyStream Test Suite / code-quality (pull_request) Has been cancelled
EasyStream Test Suite / integration-test (pull_request) Has been cancelled

This commit is contained in:
SamiAhmed7777
2025-12-15 17:28:21 -08:00
parent 3bf64b1058
commit f0f346deb9
54 changed files with 11060 additions and 484 deletions

View File

@@ -0,0 +1,421 @@
# 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
<script src="/f_scripts/fe/js/api-helper.js"></script>
```
### 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