Skip to main content

Introduction

The Plivo Browser SDK supports two authentication methods for registering SIP endpoints:
  1. Username/Password: client.login(username, password)
  2. JWT Access Token: client.loginWithAccessToken(jwt) (recommended, added in v2.2.16)
JWT tokens are short-lived, server-signed tokens that authenticate a browser session against a Plivo SIP endpoint without exposing endpoint credentials to the client. This makes JWT the recommended approach for production applications.
JWT authentication requires plivo-browser-sdk v2.2.16 or later. Earlier versions only support username/password authentication.

How it works

Browser                     Your Server                   Plivo
  |                             |                           |
  | 1. Request token            |                           |
  | --------------------------> |                           |
  |                             | 2. POST /JWT/Token/       |
  |                             | ------------------------> |
  |                             |                           |
  |                             | 3. Returns signed JWT     |
  |                             | <------------------------ |
  | 4. Return JWT               |                           |
  | <-------------------------- |                           |
  |                             |                           |
  | 5. loginWithAccessToken()   |                           |
  | -------------------------------------------------------->
  |                             |                           |
  | 6. SIP REGISTER (WebRTC)    |                           |
  | <--------------------------------------------------------
  1. Your browser app requests a JWT from your backend server.
  2. Your server calls the Plivo REST API to generate a signed token.
  3. Plivo returns a signed JWT.
  4. Your server passes the JWT to the browser.
  5. The Browser SDK uses the JWT to register with Plivo via loginWithAccessToken().
  6. Plivo validates the token and completes SIP registration over WebRTC.
JWTs must be generated server-side via the Plivo REST API. Locally-signed JWTs (using libraries like jsonwebtoken) are rejected by Plivo’s SIP infrastructure, even if signed with your auth_token.

Prerequisites

Before generating JWT tokens, you need:
  • A Plivo account with auth_id and auth_token (sign up)
  • A Plivo Application that defines your answer and hangup webhook URLs
  • A Plivo Endpoint linked to the application
  • plivo-browser-sdk v2.2.16+ installed in your frontend
If you don’t have an application and endpoint yet, see Setting up an application and endpoint below.

Generating a JWT token

Use the Plivo REST API to generate a signed JWT for a specific endpoint.

API endpoint

POST https://api.plivo.com/v1/Account/{auth_id}/JWT/Token/

Authentication

Use HTTP Basic Auth with your Plivo auth_id and auth_token.

Request body

FieldTypeRequiredDescription
issstringYesYour Plivo auth_id.
substringYesThe subject identifier for the token.
nbfnumberYesNot Before timestamp (Unix seconds). The token is invalid before this time.
expnumberYesExpiration timestamp (Unix seconds). The token is invalid after this time. Maximum allowed validity is 24 hours.
perobjectYesPermissions object. See Permissions.
appstringNoPlivo Application ID. Associates the session with a specific application for call routing.

Permissions

The per object controls what the authenticated endpoint can do:
{
  "voice": {
    "incoming_allow": true,
    "outgoing_allow": true
  }
}
FieldTypeDescription
incoming_allowbooleanWhether the endpoint can receive inbound calls.
outgoing_allowbooleanWhether the endpoint can make outbound calls.

Response

A successful request returns a JSON object containing the signed JWT:
{
  "api_id": "2c09a7fc-1234-11ee-b979-0242ac110002",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImN0eSI6InBsaXZvO3Y9MSJ9..."
}
The returned JWT has the following structure:
PartDetails
Header{ "alg": "HS256", "typ": "JWT", "cty": "plivo;v=1" }
PayloadContains iss, sub, nbf, exp, per, app, plus Plivo-added fields
SignatureHMAC-SHA256, signed by Plivo (not your auth_token)
The cty: "plivo;v=1" header is added automatically by the Plivo REST API when generating tokens. Plivo’s server validates this field during SIP registration.

Server-side examples

// Express.js route handler
app.post("/api/plivo-token", async (req, res) => {
  const authId = process.env.PLIVO_AUTH_ID;
  const authToken = process.env.PLIVO_AUTH_TOKEN;
  const now = Math.floor(Date.now() / 1000);

  const response = await fetch(
    `https://api.plivo.com/v1/Account/${authId}/JWT/Token/`,
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Basic ${Buffer.from(`${authId}:${authToken}`).toString("base64")}`,
      },
      body: JSON.stringify({
        iss: authId,
        sub: "myendpoint",         // endpoint username
        nbf: now,
        exp: now + 300,            // 5 minutes
        per: {
          voice: {
            incoming_allow: true,
            outgoing_allow: true,
          },
        },
        app: "77241325312960404",  // application ID
      }),
    }
  );

  if (!response.ok) {
    return res.status(500).json({ error: "Failed to generate token" });
  }

  const data = await response.json();
  res.json({ token: data.token });
});

Browser SDK integration

Login with a JWT

After fetching a JWT from your server, use loginWithAccessToken() to register with Plivo:
import Plivo from "plivo-browser-sdk";

// Initialize the SDK
const plivoBrowserSdk = new window.Plivo({
  debug: "INFO",
  permOnClick: true,
  enableTracking: true,
});

// Set up event handlers
plivoBrowserSdk.client.on("onLogin", () => {
  console.log("Registered with Plivo successfully");
  // Ready to make or receive calls
});

plivoBrowserSdk.client.on("onLoginFailed", (errorCode) => {
  const errorMessage = plivoBrowserSdk.client.getErrorStringByErrorCodes(errorCode);
  console.error("Login failed:", errorCode, errorMessage);
});

// Fetch JWT from your server
const response = await fetch("/api/plivo-token", { method: "POST" });
const { token } = await response.json();

// Register using JWT
plivoBrowserSdk.client.loginWithAccessToken(token);

Making a call after login

Once registered, you can make outbound calls:
plivoBrowserSdk.client.on("onCallAnswered", (callInfo) => {
  console.log("Call connected:", callInfo);
});

plivoBrowserSdk.client.on("onCallTerminated", (hangupInfo, callInfo) => {
  console.log("Call ended:", hangupInfo);
});

// Call a phone number
plivoBrowserSdk.client.call("+14155551234");

// Or call with custom SIP headers
plivoBrowserSdk.client.call("+14155551234", {
  "X-PH-SessionId": "session-abc-123",
});

Refreshing tokens

JWT tokens are short-lived. If you need to re-register (for example, after a network disconnect), fetch a new token and call loginWithAccessToken() again:
plivoBrowserSdk.client.on("onConnectionChange", async (info) => {
  if (info.state === "connected") {
    // WebSocket reconnected - re-register with a fresh token
    const response = await fetch("/api/plivo-token", { method: "POST" });
    const { token } = await response.json();
    plivoBrowserSdk.client.loginWithAccessToken(token);
  }
});

Setting up an application and endpoint

If you don’t already have a Plivo Application and Endpoint, create them before generating JWT tokens.

Create an application

A Plivo Application defines the webhook URLs that Plivo calls when a browser-initiated call connects.
curl -X POST "https://api.plivo.com/v1/Account/{auth_id}/Application/" \
  -H "Content-Type: application/json" \
  -u "{auth_id}:{auth_token}" \
  -d '{
    "app_name": "my-browser-app",
    "answer_url": "https://your-server.com/answer",
    "answer_method": "POST",
    "hangup_url": "https://your-server.com/hangup",
    "hangup_method": "POST"
  }'
The response includes an app_id. Save this for creating endpoints and generating JWT tokens. For more details, see the Application API reference.

Create an endpoint

A Plivo Endpoint is a SIP identity that the Browser SDK registers as. Each endpoint must be linked to an application.
curl -X POST "https://api.plivo.com/v1/Account/{auth_id}/Endpoint/" \
  -H "Content-Type: application/json" \
  -u "{auth_id}:{auth_token}" \
  -d '{
    "username": "myendpoint",
    "password": "a-strong-random-password",
    "alias": "my-browser-endpoint",
    "app_id": "77241325312960404"
  }'
Endpoint constraints:
  • username: Alphanumeric characters only, 1-25 characters, must start with an alphabetic character.
  • alias: Letters, numbers, hyphens, and underscores only.
  • password: At least 5 characters. Only used at creation time; the Browser SDK authenticates via JWT, not the endpoint password.
The endpoint username from the response is the value you pass as sub when generating JWT tokens. For more details, see the Endpoint API reference.

Error codes

When JWT authentication fails, the onLoginFailed event returns a numeric error code. Use getErrorStringByErrorCodes() to get a human-readable message.
Error CodeError NameDescription
10001INVALID_ACCESS_TOKENThe access token is invalid.
10002INVALID_ACCESS_TOKEN_HEADERThe access token header is invalid.
10003INVALID_ACCESS_TOKEN_ISSUERThe token issuer (iss) is invalid.
10004INVALID_ACCESS_TOKEN_SUBJECTThe token subject (sub) is invalid.
10005ACCESS_TOKEN_NOT_VALID_YETThe current time is before the token’s nbf timestamp.
10006ACCESS_TOKEN_EXPIREDThe token’s exp timestamp has passed. Generate a new token.
10007INVALID_ACCESS_TOKEN_SIGNATUREThe token signature is invalid. Ensure the token was generated via the Plivo REST API.
10008INVALID_ACCESS_TOKEN_GRANTSThe per permissions object is missing or invalid.
10009EXPIRATION_EXCEEDS_MAX_ALLOWED_TIMEThe token expiration exceeds the maximum allowed duration.
10010MAX_ALLOWED_LOGIN_REACHEDThe maximum number of concurrent logins has been reached.

Handling errors in code

plivoBrowserSdk.client.on("onLoginFailed", (errorCode) => {
  const errorMessage = plivoBrowserSdk.client.getErrorStringByErrorCodes(errorCode);
  console.error(`Login failed [${errorCode}]: ${errorMessage}`);

  // Handle specific cases
  if (errorCode === 10006) {
    // Token expired - fetch a fresh one and retry
    refreshAndRelogin();
  }
});

Best practices

  1. Keep tokens short-lived. A validity of 5 minutes is recommended. The Browser SDK maintains the SIP registration after login; re-authentication is only needed when the session disconnects.
  2. Match the endpoint to the application. Each endpoint is linked to a specific application via app_id. The app field in the JWT should reference the same application the endpoint is registered to, otherwise call routing may behave unexpectedly.
  3. Never expose credentials to the browser. Your auth_id and auth_token should only be used server-side. The browser should only receive the signed JWT.
  4. One endpoint per concurrent session. While Plivo allows multiple simultaneous registrations for the same endpoint, this is only reliable for outbound-only use cases. For inbound call routing, use a unique endpoint per browser session.