# 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
