Esta página se muestra en inglés. Una traducción al español está en curso.
ScriptsMay 11, 2026·4 min de lectura

LiveKit Token Server — Sign JWTs for Room Access

Server-side token signing for LiveKit rooms. Python/Node SDKs. Per-user permissions, room scoping, TTL. Required for production.

Listo para agents

Staging seguro para este activo

Este activo primero queda en staging. El prompt copiado pide inspeccionar los archivos staged antes de activar scripts, config MCP o config global.

Stage only · 29/100Política: staging
Superficie agent
Cualquier agent MCP/CLI
Tipo
Skill
Instalación
Stage only
Confianza
Confianza: Community
Entrada
Asset
Comando de staging seguro
npx -y tokrepo@latest install 793c4a17-cd72-40f3-aba5-9cb0f5957f1d --target codex

Primero deja archivos en staging; la activación requiere revisar el README y el plan staged.

Introducción

LiveKit rooms require signed JWT access tokens — your backend signs a token with API key + secret, granting a specific identity permission to join a specific room with specific capabilities (publish, subscribe, record, data). Never sign in the browser. This is the server-side flow with Python and Node examples. Best for: any production LiveKit deployment, multi-tenant voice apps, per-user permission models. Works with: livekit-server-sdk (Python, Node, Go, Ruby, Java). Setup time: 10 minutes.


Python token endpoint (FastAPI)

from livekit import api
from fastapi import FastAPI, HTTPException, Depends
import os

app = FastAPI()

@app.post("/livekit/token")
async def issue_token(user_id: str, room: str, user = Depends(authenticated_user)):
    if not can_join_room(user, room):
        raise HTTPException(403, "not allowed in this room")

    token = (
        api.AccessToken(os.environ["LIVEKIT_API_KEY"], os.environ["LIVEKIT_API_SECRET"])
        .with_identity(user_id)
        .with_name(user.display_name)
        .with_grants(api.VideoGrants(
            room_join=True,
            room=room,
            can_publish=True,
            can_subscribe=True,
            can_publish_data=True,
        ))
        .with_ttl(timedelta(hours=1))
        .to_jwt()
    )
    return {"token": token, "url": os.environ["LIVEKIT_URL"]}

Node token endpoint (Express)

import { AccessToken } from 'livekit-server-sdk';

app.post('/livekit/token', requireAuth, async (req, res) => {
  const { userId, room } = req.body;
  if (!canJoinRoom(req.user, room)) return res.status(403).send();

  const at = new AccessToken(process.env.LIVEKIT_API_KEY, process.env.LIVEKIT_API_SECRET, {
    identity: userId,
    name: req.user.displayName,
    ttl: '1h',
  });
  at.addGrant({
    roomJoin: true,
    room,
    canPublish: true,
    canSubscribe: true,
    canPublishData: true,
  });

  res.json({ token: await at.toJwt(), url: process.env.LIVEKIT_URL });
});

Grant cheat sheet

Grant Use case
room_join Required for any participant
can_publish Participant can publish audio/video
can_subscribe Participant can hear/see others
can_publish_data Send arbitrary chat / state via DataChannel
room_admin Can mute, remove participants
room_record Can start egress recording
ingress_admin Can manage SIP / RTMP ingress

Production hardening

  • Short TTL — 1 hour max for end-user tokens. Browser refreshes via your endpoint.
  • Per-user identity — never reuse identities. user_id should be your DB primary key.
  • Server-side only — never log secrets, never ship API_SECRET to the browser.
  • Cache the SDK — instantiate once, reuse for many tokens.

FAQ

Q: Can I sign tokens in the browser? A: No — the API_SECRET would be exposed. Always sign in your backend. The browser only ever sees the resulting JWT, which has limited TTL and scoped grants.

Q: How do agents get their own token? A: Agents authenticate the same way — your worker process signs an agent identity token (with agent=True grant) before joining the room. LiveKit Cloud agent dispatchers handle this automatically when you deploy via the LiveKit CLI.

Q: What about webhooks for participant join/leave? A: Configure webhooks at cloud.livekit.io → Webhooks. Events: room_started, participant_joined, participant_left, track_published, egress_started. Verify the X-LiveKit-Signature header server-side.


Quick Use

  1. pip install livekit-api or npm install livekit-server-sdk
  2. Build an authenticated POST /livekit/token endpoint in your backend
  3. Frontend POSTs (user_id, room), gets back {token, url}, joins with the SDK

Intro

LiveKit rooms require signed JWT access tokens — your backend signs a token with API key + secret, granting a specific identity permission to join a specific room with specific capabilities (publish, subscribe, record, data). Never sign in the browser. This is the server-side flow with Python and Node examples. Best for: any production LiveKit deployment, multi-tenant voice apps, per-user permission models. Works with: livekit-server-sdk (Python, Node, Go, Ruby, Java). Setup time: 10 minutes.


Python token endpoint (FastAPI)

from livekit import api
from fastapi import FastAPI, HTTPException, Depends
import os

app = FastAPI()

@app.post("/livekit/token")
async def issue_token(user_id: str, room: str, user = Depends(authenticated_user)):
    if not can_join_room(user, room):
        raise HTTPException(403, "not allowed in this room")

    token = (
        api.AccessToken(os.environ["LIVEKIT_API_KEY"], os.environ["LIVEKIT_API_SECRET"])
        .with_identity(user_id)
        .with_name(user.display_name)
        .with_grants(api.VideoGrants(
            room_join=True,
            room=room,
            can_publish=True,
            can_subscribe=True,
            can_publish_data=True,
        ))
        .with_ttl(timedelta(hours=1))
        .to_jwt()
    )
    return {"token": token, "url": os.environ["LIVEKIT_URL"]}

Node token endpoint (Express)

import { AccessToken } from 'livekit-server-sdk';

app.post('/livekit/token', requireAuth, async (req, res) => {
  const { userId, room } = req.body;
  if (!canJoinRoom(req.user, room)) return res.status(403).send();

  const at = new AccessToken(process.env.LIVEKIT_API_KEY, process.env.LIVEKIT_API_SECRET, {
    identity: userId,
    name: req.user.displayName,
    ttl: '1h',
  });
  at.addGrant({
    roomJoin: true,
    room,
    canPublish: true,
    canSubscribe: true,
    canPublishData: true,
  });

  res.json({ token: await at.toJwt(), url: process.env.LIVEKIT_URL });
});

Grant cheat sheet

Grant Use case
room_join Required for any participant
can_publish Participant can publish audio/video
can_subscribe Participant can hear/see others
can_publish_data Send arbitrary chat / state via DataChannel
room_admin Can mute, remove participants
room_record Can start egress recording
ingress_admin Can manage SIP / RTMP ingress

Production hardening

  • Short TTL — 1 hour max for end-user tokens. Browser refreshes via your endpoint.
  • Per-user identity — never reuse identities. user_id should be your DB primary key.
  • Server-side only — never log secrets, never ship API_SECRET to the browser.
  • Cache the SDK — instantiate once, reuse for many tokens.

FAQ

Q: Can I sign tokens in the browser? A: No — the API_SECRET would be exposed. Always sign in your backend. The browser only ever sees the resulting JWT, which has limited TTL and scoped grants.

Q: How do agents get their own token? A: Agents authenticate the same way — your worker process signs an agent identity token (with agent=True grant) before joining the room. LiveKit Cloud agent dispatchers handle this automatically when you deploy via the LiveKit CLI.

Q: What about webhooks for participant join/leave? A: Configure webhooks at cloud.livekit.io → Webhooks. Events: room_started, participant_joined, participant_left, track_published, egress_started. Verify the X-LiveKit-Signature header server-side.


Source & Thanks

Built by LiveKit. Licensed under Apache-2.0.

livekit/python-sdks, livekit/server-sdk-js

🙏

Fuente y agradecimientos

Built by LiveKit. Licensed under Apache-2.0.

livekit/python-sdks, livekit/server-sdk-js

Discusión

Inicia sesión para unirte a la discusión.
Aún no hay comentarios. Sé el primero en compartir tus ideas.

Activos relacionados