Authentication Overview

LILA supports two authentication modes: Basic (API Key only) for development, and Secure (JWT tokens) for production. Secure mode ensures each user only sees their own data. This guide explains when to use each mode and shows you how to implement secure user authentication.

Authentication Modes

API key vs JWT authentication: when to use each.

Basic Mode (API Key Only)

Use Case: Development, testing, non-sensitive data

How it works:

<script type="module" src="https://embed.getlila.one/loader.js"></script>
<lila-widget
  api-key="pk_live_abc123..."
  user-id="user_12345"
  user-role="customer">
</lila-widget>

Characteristics:

  • ✅ Simplest integration
  • ✅ No JWT generation needed
  • ✅ Works for testing
  • ❌ No cryptographic verification
  • ❌ Less secure for production

Best For:

  • Development environments
  • Testing and demos
  • Internal tools

Secure Mode (JWT Token)

Use Case: User-specific data, sensitive information, production applications

How it works:

<script type="module" src="https://embed.getlila.one/loader.js"></script>
<lila-widget
  api-key="pk_live_abc123..."
  jwt-token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...">
</lila-widget>

Characteristics:

  • ✅ User identification
  • ✅ Per-user data isolation
  • ✅ Cryptographic verification
  • ✅ Enterprise-grade security
  • ❌ Requires backend JWT generation
  • ❌ Slightly more complex setup

Best For:

  • E-commerce customer portals
  • SaaS application dashboards
  • Enterprise internal tools
  • Any authenticated application

JWT Token Structure

JSON Web Token (JWT) is a secure way to transmit user information between your backend and LILA. The token contains user identity claims that LILA validates on every request.

Example JWT:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiMTIzNDUiLCJlbWFpbCI6InVzZXJAZXhhbXBsZS5jb20iLCJpYXQiOjE2OTg0MjAwMDAsImV4cCI6MTY5ODQyNzIwMH0.signature

Decoded Structure:

Header:

{
  "alg": "HS256",
  "typ": "JWT"
}

Payload:

{
  "user_id": "12345",
  "email": "[email protected]",
  "name": "John Doe",
  "role": "customer",
  "iat": 1698420000,
  "exp": 1698427200
}

Signature: Cryptographic signature using your JWT secret

Required JWT Claims

LILA requires these claims in JWT payload:

ClaimTypeRequiredDescription
user_idstring✅ YesUnique user identifier
iatnumber✅ YesIssued at timestamp
expnumber✅ YesExpiration timestamp
emailstring⚠️ RecommendedUser email for identification
namestring⚠️ RecommendedUser display name

Optional Claims:

  • role - User role (admin, customer, etc.)
  • tenant_id - Multi-tenant identifier (for your application’s tenant isolation)

JWT Security Best Practices

DO:

  • ✅ Store JWT secret in environment variables
  • ✅ Use strong, random secrets (min 32 characters)
  • ✅ Set reasonable expiration (1-2 hours recommended)
  • ✅ Generate tokens on backend only
  • ✅ Use HTTPS in production
  • ✅ Implement token refresh mechanism

DON’T:

  • ❌ Expose JWT secret in frontend code
  • ❌ Store sensitive data in JWT payload (it’s base64, not encrypted!)
  • ❌ Set infinite expiration (exp: null)
  • ❌ Reuse tokens across different projects
  • ❌ Generate tokens in browser JavaScript

Implementation Flow

Backend Token Generation

Your backend generates JWT when user logs in:

User Login

Backend Authenticates

Generate JWT with user info

Return JWT to frontend

Frontend passes JWT to LILA widget

LILA Token Validation

LILA API validates JWT on every request:

Widget sends query + JWT

LILA validates signature with JWT secret

Check expiration (exp claim)

Extract user_id for data filtering

Execute query with user context

Return personalized results

Token Expiration

Token expiration and refresh handling for LILA JWT authentication.

Why Tokens Expire

Security best practice: Short-lived tokens reduce risk if compromised. LILA validates the exp claim on every request and rejects expired tokens.

Recommended Expiration:

  • Development: 24 hours
  • Production: 1-2 hours
  • High Security: 15-30 minutes

Handling Expiration

When a token expires, generate a fresh one from your backend and update the widget:

// Update widget with new token
const widget = document.querySelector('lila-widget');
widget.setAttribute('jwt-token', newToken);

Your application should handle token refresh based on your existing session management. Generate a new LILA JWT whenever your user’s session is refreshed.

Testing Authentication

Verify JWT Configuration

Check Dashboard Settings:

  1. Go to LILA Dashboard
  2. Select your project
  3. Navigate to SettingsSetup & Integration
  4. Find the JWT Secret in the Security section
  5. Copy your JWT Secret

Test Token Generation

Use jwt.io to verify your tokens:

  1. Paste your generated token
  2. Check header algorithm is HS256
  3. Verify payload contains required claims
  4. Enter your JWT secret to validate signature

Debug Authentication Issues

Common Problems:

“Invalid JWT signature”

  • JWT secret doesn’t match Dashboard settings
  • Using wrong algorithm (must be HS256)
  • Token corrupted during transmission

“Token expired”

  • exp claim in past
  • Server clock skew
  • Need to implement token refresh

“Missing required claim: user_id”

  • JWT payload doesn’t include user_id
  • Claim name typo (userId vs user_id)

Language-Specific Guides

Detailed JWT implementation for your platform:

Security Checklist

Before going to production:

  • JWT secret stored in environment variables (not hardcoded)
  • Tokens generated on backend only (never in browser)
  • Reasonable expiration set (1-2 hours)
  • HTTPS enabled in production
  • JWT secret is 32+ characters, random
  • No sensitive data in JWT payload
  • User IDs properly sanitized

Migration Guide

From Basic to Secure Mode

Step 1: Enable JWT in Dashboard

  1. Go to SettingsSetup & Integration
  2. Find Security section and enable “Require JWT”
  3. Copy your JWT secret

Step 2: Implement Backend Token Generation

// Add JWT generation to your auth flow
function generateLilaToken($user) {
    $payload = [
        'user_id' => (string) $user->id,
        'email' => $user->email,
        'name' => $user->name,
        'iat' => time(),
        'exp' => time() + (60 * 60 * 2) // 2 hours
    ];

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

Step 3: Update Widget Code

<!-- Before (Basic mode) -->
<lila-widget
  api-key="{{ config('lila.api_key') }}"
  user-id="{{ Auth::id() }}"
  user-role="customer">
</lila-widget>

<!-- After (Secure mode) -->
@auth
<lila-widget
  api-key="{{ config('lila.api_key') }}"
  jwt-token="{{ generateLilaToken(Auth::user()) }}">
</lila-widget>
@endauth

Step 4: Test

  1. Verify widget loads for authenticated users
  2. Check queries execute successfully
  3. Verify user context is passed correctly

Next Steps