Skip to main content

Generating tokens

Generate tokens for your frontend

In order for frontend apps to connect to LiveKit rooms, they need a token generated by your backend server. In this guide, we'll walk through how to set up a server to generate tokens for your frontend.

1. Install LiveKit Server SDK

go get github.com/livekit/server-sdk-go/v2
# yarn:
yarn add livekit-server-sdk
# npm:
npm install livekit-server-sdk --save
# Add to your Gemfile
gem 'livekit-server-sdk'
pip install livekit-api
# Cargo.toml
[package]
name = "example_server"
version = "0.1.0"
edition = "2021"
[dependencies]
livekit-api = "0.2.0"
# Remaining deps are for the example server
warp = "0.3"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tokio = { version = "1", features = ["full"] }
composer require agence104/livekit-server-sdk

2. Keys and Configuration

Create a new file at development.env and with your API Key and Secret:

export LIVEKIT_API_KEY=<your API Key>
export LIVEKIT_API_SECRET=<your API Secret>

3. Make an endpoint that returns a token

Create a server:

// server.go
import (
"net/http"
"log"
"time"
"os"
"github.com/livekit/protocol/auth"
)
func getJoinToken(room, identity string) string {
at := auth.NewAccessToken(os.Getenv("LIVEKIT_API_KEY"), os.Getenv("LIVEKIT_API_SECRET"))
grant := &auth.VideoGrant{
RoomJoin: true,
Room: room,
}
at.AddGrant(grant).
SetIdentity(identity).
SetValidFor(time.Hour)
token, _ := at.ToJWT()
return token
}
func main() {
http.HandleFunc("/getToken", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(getJoinToken("my-room", "identity")))
})
log.Fatal(http.ListenAndServe(":8080", nil))
}
// server.js
import express from 'express';
import { AccessToken } from 'livekit-server-sdk';
const createToken = async () => {
// If this room doesn't exist, it'll be automatically created when the first
// participant joins
const roomName = 'quickstart-room';
// Identifier to be used for participant.
// It's available as LocalParticipant.identity with livekit-client SDK
const participantName = 'quickstart-username';
const at = new AccessToken(process.env.LIVEKIT_API_KEY, process.env.LIVEKIT_API_SECRET, {
identity: participantName,
// Token to expire after 10 minutes
ttl: '10m',
});
at.addGrant({ roomJoin: true, room: roomName });
return await at.toJwt();
};
const app = express();
const port = 3000;
app.get('/getToken', async (req, res) => {
res.send(await createToken());
});
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
# server.rb
require 'livekit'
require 'sinatra'
def createToken()
token = LiveKit::AccessToken.new(api_key: ENV['LIVEKIT_API_KEY'], api_secret: ENV['LIVEKIT_API_SECRET'])
token.identity = 'quickstart-identity'
token.name = 'quickstart-name'
token.add_grant(roomJoin: true, room: 'room-name')
token.to_jwt
end
get '/getToken' do
createToken
end
# server.py
import os
from livekit import api
from flask import Flask
app = Flask(__name__)
@app.route('/getToken')
def getToken():
token = api.AccessToken(os.getenv('LIVEKIT_API_KEY'), os.getenv('LIVEKIT_API_SECRET')) \
.with_identity("identity") \
.with_name("my name") \
.with_grants(api.VideoGrants(
room_join=True,
room="my-room",
))
return token.to_jwt()
// src/main.rs
use livekit_api::access_token;
use warp::Filter;
use serde::{Serialize, Deserialize};
use std::env;
#[tokio::main]
async fn main() {
// Define the route
let create_token_route = warp::path("create-token")
.map(|| {
let token = create_token().unwrap();
warp::reply::json(&TokenResponse { token })
});
// Start the server
warp::serve(create_token_route).run(([127, 0, 0, 1], 3030)).await;
}
// Token creation function
fn create_token() -> Result<String, access_token::AccessTokenError> {
let api_key = env::var("LIVEKIT_API_KEY").expect("LIVEKIT_API_KEY is not set");
let api_secret = env::var("LIVEKIT_API_SECRET").expect("LIVEKIT_API_SECRET is not set");
let token = access_token::AccessToken::with_api_key(&api_key, &api_secret)
.with_identity("identity")
.with_name("name")
.with_grants(access_token::VideoGrants {
room_join: true,
room: "my-room".to_string(),
..Default::default()
})
.to_jwt();
return token
}
// Response structure
#[derive(Serialize, Deserialize)]
struct TokenResponse {
token: String,
}
// If this room doesn't exist, it'll be automatically created when the first
// participant joins.
$roomName = 'name-of-room';
// The identifier to be used for participant.
$participantName = 'user-name';
// Define the token options.
$tokenOptions = (new AccessTokenOptions())
->setIdentity($participantName);
// Define the video grants.
$videoGrant = (new VideoGrant())
->setRoomJoin()
->setRoomName($roomName);
// Initialize and fetch the JWT Token.
$token = (new AccessToken(getenv('LIVEKIT_API_KEY'), getenv('LIVEKIT_API_SECRET')))
->init($tokenOptions)
->setGrant($videoGrant)
->toJwt();

Load the environment variables and run the server:

$ source development.env
$ go run server.go
$ source development.env
$ node server.js
$ source development.env
$ ruby server.rb
$ source development.env
$ python server.py
$ source development.env
$ cargo r src/main.rs
$ source development.env
$ php server.php
Note

See the Authentication page for more information on how to generate tokens with custom permissions.

4. Create a frontend app to connect

Create a frontend app that fetches a token from the server we just made, then uses it to connect to a LiveKit room: