Files
easystream-main/docs/API_AUTHENTICATION_GUIDE.md
SamiAhmed7777 f0f346deb9
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
Sync current dev state
2025-12-15 17:28:21 -08:00

8.4 KiB

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:

{
    "identifier": "username or email",
    "password": "your_password",
    "expires_in": 86400  // Optional: token expiry in seconds (default: 24 hours)
}

Response (Success):

{
    "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):

{
    "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):

{
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Response (Success):

{
    "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:

{
    "identifier": "username or email",
    "password": "your_password",
    "remember_me": false
}

Response:

{
    "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:

<script src="/f_scripts/fe/js/api-helper.js"></script>

Initialize API Client

// API client is automatically initialized as window.api
const api = window.api; // or new EasyStreamAPI()

Authentication Examples

Login and Get Token

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

if (api.isAuthenticated()) {
    console.log('User is authenticated');
} else {
    console.log('User is not authenticated');
}

Get Current User Info

try {
    const userData = await api.getCurrentUser();
    console.log('Current user:', userData.user);
} catch (error) {
    console.error('Not authenticated:', error);
}

Logout

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

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

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

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

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:

// 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

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

curl -X GET http://localhost:8083/api/auth.php?action=verify_token \
  -H "Authorization: Bearer YOUR_JWT_TOKEN_HERE"

Authenticated API Request

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):

$.post('/some_endpoint.php', { action: 'do_something' }, function(data) {
    console.log(data);
});

After (Fetch with JWT):

api.post('/some_endpoint.php', { action: 'do_something' })
    .then(data => console.log(data))
    .catch(error => console.error(error));

Environment Configuration

Update your .env file:

# JWT Configuration
JWT_SECRET=9a652ee880c41bafb0a81d38d54b029d63903eeaafccaa8c12880a913931f63b
JWT_EXPIRY=86400

# CORS Configuration (for separate frontends)
CORS_ORIGIN=http://localhost:3000

Error Handling

Common Errors

401 Unauthorized

{
    "success": false,
    "message": "Invalid or expired token"
}

Solution: Re-login to get a new token.

403 Forbidden

{
    "success": false,
    "message": "Access denied"
}

Solution: User doesn't have permission for this resource.

429 Rate Limited

{
    "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