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": "user@example.com",
"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:
| Claim | Type | Required | Description |
|---|---|---|---|
user_id | string | ✅ Yes | Unique user identifier |
iat | number | ✅ Yes | Issued at timestamp |
exp | number | ✅ Yes | Expiration timestamp |
email | string | ⚠️ Recommended | User email for identification |
name | string | ⚠️ Recommended | User 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:
- Go to LILA Dashboard
- Select your project
- Navigate to Settings → Setup & Integration
- Find the JWT Secret in the Security section
- Copy your JWT Secret
Test Token Generation
Use jwt.io to verify your tokens:
- Paste your generated token
- Check header algorithm is
HS256 - Verify payload contains required claims
- 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”
expclaim 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 (
userIdvsuser_id)
Language-Specific Guides
Detailed JWT implementation for your platform:
- PHP/Laravel - Complete Laravel integration
- JavaScript/Node.js - Express.js examples
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
- Go to Settings → Setup & Integration
- Find Security section and enable “Require JWT”
- 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
- Verify widget loads for authenticated users
- Check queries execute successfully
- Verify user context is passed correctly
Next Steps
- PHP/Laravel JWT Guide - Laravel implementation
- JavaScript JWT Guide - Node.js examples
- Widget Configuration - Widget setup