Add detailed API: - Complete API documentation for In Format Usage flow diagrams for authentication and booking processes - Comprehensive endpoint descriptions with request/response examples - Detailed authentication and booking flow explanations - Structured documentation for health checks, authentication, and booking endpoints -: - Includes JWT authentication details usage - Provides clear API usage patterns for users and clients and administrators system interactions - Enhances project documentation with provides clear, structured API reference - Improves developer and user understanding of system capabilities
8.3 KiB
Jitsi JWT Authentication Implementation
Overview
The system now uses JWT (JSON Web Token) authentication for Jitsi meetings, providing proper moderator privileges and secure meeting access. This replaces the previous URL parameter approach with industry-standard JWT tokens.
How It Works
JWT Token Structure
Each meeting link includes a JWT token that contains:
{
"context": {
"user": {
"name": "John Doe",
"email": "john@example.com",
"moderator": "true" // "true" for admin, "false" for regular users
}
},
"room": "booking-123-1234567890-abc123",
"aud": "jitsi",
"iss": "your-app-id",
"sub": "your-jitsi-domain.com",
"exp": 1234567890 // 24 hour expiry
}
Meeting URL Format
With JWT (Recommended):
https://meet.jit.si/booking-123-abc?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Fallback (No JWT configured):
https://meet.jit.si/booking-123-abc#userInfo.displayName="John Doe"
Configuration
Option 1: Public Jitsi (meet.jit.si)
For testing or using public Jitsi servers, leave JWT configuration empty:
JITSI_BASE_URL=https://meet.jit.si
JITSI_API_KEY=
JITSI_APP_ID=
Note: Public Jitsi doesn't enforce JWT authentication, so the system will fall back to URL parameters. Moderator privileges won't work properly on public servers.
Option 2: Self-Hosted Jitsi with JWT
For production with proper moderator control, configure your self-hosted Jitsi:
JITSI_BASE_URL=https://meet.yourdomain.com
JITSI_API_KEY=your_jwt_secret_key_here
JITSI_APP_ID=your_app_id_here
Setting Up Self-Hosted Jitsi with JWT
1. Install Jitsi Meet
Follow the official guide: https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-quickstart
2. Enable JWT Authentication
Edit /etc/prosody/conf.avail/yourdomain.com.cfg.lua:
VirtualHost "yourdomain.com"
authentication = "token"
app_id = "your_app_id"
app_secret = "your_jwt_secret_key"
allow_empty_token = false
3. Configure Jicofo
Edit /etc/jitsi/jicofo/sip-communicator.properties:
org.jitsi.jicofo.auth.URL=XMPP:yourdomain.com
4. Restart Services
systemctl restart prosody
systemctl restart jicofo
systemctl restart jitsi-videobridge2
5. Update Your .env File
JITSI_BASE_URL=https://meet.yourdomain.com
JITSI_API_KEY=your_jwt_secret_key
JITSI_APP_ID=your_app_id
API Response Examples
GET /api/bookings
{
"bookings": [
{
"id": 123,
"jitsi_room_id": "booking-123-1234567890-abc123",
"jitsi_room_url": "https://meet.jit.si/booking-123-1234567890-abc123",
"personalized_meeting_url": "https://meet.jit.si/booking-123-1234567890-abc123?jwt=eyJhbGc..."
}
]
}
GET /api/admin/bookings
{
"bookings": [
{
"id": 123,
"jitsi_room_id": "booking-123-1234567890-abc123",
"jitsi_room_url": "https://meet.jit.si/booking-123-1234567890-abc123",
"admin_meeting_url": "https://meet.jit.si/booking-123-1234567890-abc123?jwt=eyJhbGc..."
}
]
}
GET /api/meetings/:id/link
{
"booking_id": 123,
"meeting_url": "https://meet.jit.si/booking-123-1234567890-abc123?jwt=eyJhbGc...",
"display_name": "John Doe",
"is_admin": false
}
User vs Admin Differences
Regular User Token
{
"context": {
"user": {
"name": "John Doe",
"email": "john@example.com",
"moderator": "false"
}
}
}
Permissions:
- Can join meeting
- Can share screen
- Can mute/unmute themselves
- Cannot kick participants
- Cannot end meeting for all
Admin User Token
{
"context": {
"user": {
"name": "Dr. Smith",
"email": "dr.smith@example.com",
"moderator": "true"
}
}
}
Permissions:
- All regular user permissions
- Can kick participants
- Can mute other participants
- Can end meeting for all
- Can start/stop recording (if configured)
- Can enable/disable lobby
Email Notifications
All email notifications now include JWT-authenticated links:
Meeting Info Email
<a href="https://meet.jit.si/booking-123?jwt=eyJhbGc...">Join Meeting</a>
Reminder Email
<a href="https://meet.jit.si/booking-123?jwt=eyJhbGc...">Join Meeting</a>
Security Features
Token Expiration
- Tokens expire after 24 hours
- Users must request a new link after expiration
- Prevents unauthorized access to old meetings
Moderator Control
- Only users with
is_admin: trueget moderator tokens - Moderator status is cryptographically signed in JWT
- Cannot be tampered with by users
Room Isolation
- Each booking gets a unique room ID
- Room name is embedded in JWT
- Token only works for the specified room
Testing
Test JWT Generation
# Start the server
go run cmd/server/main.go
# Get a meeting link as regular user
curl -H "Authorization: Bearer <user_token>" \
http://localhost:8080/api/meetings/123/link
# Get a meeting link as admin
curl -H "Authorization: Bearer <admin_token>" \
http://localhost:8080/api/admin/bookings
Verify JWT Token
Use https://jwt.io to decode and verify your tokens:
- Copy the JWT from the meeting URL
- Paste into jwt.io debugger
- Verify the payload contains correct user info
- Check moderator field is "true" for admins
Test Moderator Privileges
- Create two bookings
- Join one as regular user
- Join another as admin
- Verify admin can:
- See moderator controls
- Kick participants
- End meeting for all
Troubleshooting
Issue: "Room locked" or "Authentication failed"
Cause: JWT not configured or invalid
Solution:
- Check
JITSI_API_KEYandJITSI_APP_IDare set - Verify they match your Jitsi server configuration
- Ensure Jitsi server has JWT authentication enabled
Issue: Admin doesn't have moderator privileges
Cause: JWT not being used or moderator claim not set
Solution:
- Verify
JITSI_API_KEYis configured - Check admin user has
is_admin: truein database - Decode JWT token and verify
moderator: "true"
Issue: Token expired error
Cause: JWT token older than 24 hours
Solution:
- Request a new meeting link
- Tokens are generated fresh on each API call
- Consider reducing expiry time if needed
Issue: Fallback to URL parameters
Cause: JWT configuration missing
Solution:
- This is expected behavior when JWT not configured
- For production, configure JWT authentication
- URL parameters work but don't enforce moderator privileges
Migration from URL Parameters
Before (URL Parameters)
https://meet.jit.si/room#userInfo.displayName="John"&config.startWithAudioMuted=false
Problems:
- No real moderator enforcement
- Anyone can modify URL parameters
- No security
After (JWT Authentication)
https://meet.jit.si/room?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Benefits:
- Cryptographically signed tokens
- True moderator enforcement
- Secure and tamper-proof
- Industry standard
Best Practices
- Use Self-Hosted Jitsi: For production, always use self-hosted Jitsi with JWT
- Rotate Secrets: Regularly rotate your
JITSI_API_KEY - Monitor Token Usage: Log token generation for audit purposes
- Set Appropriate Expiry: 24 hours is reasonable, adjust based on needs
- Test Moderator Controls: Regularly verify admin privileges work correctly
Advanced Configuration
Custom Token Expiry
Edit internal/services/jitsi_service.go:
ExpiresAt: jwt.NewNumericDate(time.Now().Add(2 * time.Hour)), // 2 hour expiry
Additional JWT Claims
Add custom claims to the JWT:
type JitsiClaims struct {
Context JitsiContext `json:"context"`
Room string `json:"room"`
Avatar string `json:"avatar,omitempty"` // User avatar URL
jwt.RegisteredClaims
}
Multiple Jitsi Servers
Support multiple Jitsi servers by environment:
func (j *jitsiService) getJitsiURL() string {
if os.Getenv("ENVIRONMENT") == "production" {
return "https://meet.production.com"
}
return "https://meet.staging.com"
}