JWT with PHP

Generate JWT tokens in PHP to connect your application users to LILA’s AI chatbot. For Laravel-specific integration with middleware and services, see the Laravel Guide.

Prerequisites

  • PHP 8.1+ (8.2+ recommended)
  • Composer

Installation

composer require firebase/php-jwt

Basic JWT Generation

Create a JWT token for LILA with this function:

<?php

require_once 'vendor/autoload.php';

use Firebase\JWT\JWT;

function generateLilaToken($userId, $userEmail, $userName) {
    $jwtSecret = $_ENV['LILA_JWT_SECRET'];

    $payload = [
        'user_id' => (string) $userId,  // Must be string
        'email' => $userEmail,
        'name' => $userName,
        'iat' => time(),
        'exp' => time() + (60 * 60 * 2), // 2 hours
    ];

    return JWT::encode($payload, $jwtSecret, 'HS256');
}

// Usage
$token = generateLilaToken(12345, '[email protected]', 'John Doe');

Token Validation

<?php

use Firebase\JWT\JWT;
use Firebase\JWT\Key;

function validateLilaToken($token) {
    $jwtSecret = $_ENV['LILA_JWT_SECRET'];

    try {
        return JWT::decode($token, new Key($jwtSecret, 'HS256'));
    } catch (Firebase\JWT\ExpiredException $e) {
        return ['error' => 'Token expired'];
    } catch (Firebase\JWT\SignatureInvalidException $e) {
        return ['error' => 'Invalid signature'];
    } catch (Exception $e) {
        return ['error' => $e->getMessage()];
    }
}

// Usage
$decoded = validateLilaToken($token);
if (!isset($decoded['error'])) {
    echo "Valid token for user: " . $decoded->user_id;
}

Token Refresh Endpoint

<?php

require_once 'vendor/autoload.php';

use Firebase\JWT\JWT;

// Load environment variables
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();

// Check authentication
session_start();
if (!isset($_SESSION['user_id'])) {
    http_response_code(401);
    echo json_encode(['error' => 'Authentication required']);
    exit;
}

// Token refresh endpoint
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $_SERVER['REQUEST_URI'] === '/api/lila/refresh-token') {
    $user = getUserById($_SESSION['user_id']); // Your user fetch function

    $payload = [
        'user_id' => (string) $user->id,
        'email' => $user->email,
        'name' => $user->name,
        'iat' => time(),
        'exp' => time() + (60 * 60 * 2),
    ];

    $token = JWT::encode($payload, $_ENV['LILA_JWT_SECRET'], 'HS256');

    header('Content-Type: application/json');
    echo json_encode([
        'token' => $token,
        'expires_in' => 7200,
    ]);
    exit;
}

HTML Integration

<!DOCTYPE html>
<html>
<head>
    <script type="module" src="https://embed.getlila.one/loader.js"></script>
</head>
<body>
    <?php if (isset($_SESSION['user_id'])): ?>
        <?php $token = generateLilaToken($_SESSION['user_id'], $userEmail, $userName); ?>
        <lila-widget
            api-key="<?php echo $_ENV['LILA_API_KEY']; ?>"
            jwt-token="<?php echo $token; ?>">
        </lila-widget>
    <?php endif; ?>
</body>
</html>

Production Checklist

  • JWT secret stored in environment variables
  • Secret is 32+ characters, randomly generated
  • Token expiration set to 1-2 hours
  • HTTPS enabled in production
  • User ID cast to string in JWT payload

Troubleshooting

Common PHP JWT issues and solutions:

“Invalid signature” Error

Cause: JWT secret doesn’t match Dashboard

Solution:

  1. Copy secret from Dashboard → Settings → Setup & Integration
  2. Update LILA_JWT_SECRET in your environment

”user_id claim missing” Error

Cause: User ID not in JWT payload

Solution: Ensure payload includes user_id as string:

'user_id' => (string) $user->id, // NOT just $user->id

Token Expires Immediately

Cause: Server time incorrect or exp calculation wrong

Solution:

// Correct (seconds since epoch)
'exp' => time() + (60 * 60 * 2)

// WRONG
'exp' => new DateTime('+2 hours') // Returns object, not timestamp

“Class ‘JWT’ not found”

Cause: firebase/php-jwt not installed

Solution:

composer require firebase/php-jwt
composer dump-autoload

Next Steps