livqenoDocs

Live StreamingAuthentication

Live Streaming Authentication

Hosts and viewers get different credentials. A viewer's token can never publish.

This page explains the credentials people use to join a live stream, and why a viewer can never broadcast.

Where this fits: this is the same token model as the rest of Livqeno. Your backend holds the API key, and your app only ever gets short-lived tokens (see Access tokens). The difference is that a live-stream credential bundles two tokens, one for the video and one for the chat, and which call your backend makes decides the person's role.

There are two kinds of credential:

  • a host credential, which can broadcast, and
  • a viewer credential, which can only watch.

Your backend makes them with the API key:

// Host/co-host — full publish permission, chat ADMIN/MODERATOR scope
const hostCredential = await livqeno.liveStreams.addHost(streamId, { identity: 'alice', role: 'HOST' });
 
// Viewer — subscribe-only, chat MEMBER scope
const viewerCredential = await livqeno.liveStreams.createViewerToken(streamId, 'carol');

What each role gets

RolePublish video/audioChat scopeCan add/remove hosts
HOSTYesADMINYes
CO_HOSTYesMODERATORNo
ViewerNoMEMBERNo

Hosts and co-hosts can publish the same things. The difference is their chat scope. Adding and removing hosts is always done by your backend, so your app decides who may do it. See Hosts & co-hosts.

What's inside a credential

Both calls return the same shape:

FieldWhat it is
streamIdThe stream to join.
identityThe user this credential is for.
roleHOST, CO_HOST, or VIEWER. For your UI only. The real permissions are signed into the tokens.
rtcA normal RTC token grant: token, endpoint, iceServers, and more.
chatA normal chat token for the stream's conversation.
chatRootMessageIdThe hidden message that reactions attach to.

Send the whole object to the app, unchanged. LiveStream.join() reads all of it.

How long a credential lasts

The RTC token inside expires like any RTC token. You don't set the lifetime on these calls, so it uses the default (10 minutes in the stock configuration).

  • It only matters for joining. A host who joined in time isn't kicked out when the token expires mid-stream.
  • It matters again if they need to reconnect. See Network quality.
  • To get fresh credentials, call addHost or createViewerToken again for the same identity.

A viewer can't become a host

This is the key safety rule of Live Streaming. Even if someone edits your app or replays a request, a viewer can't broadcast:

  • The viewer-token request has no role field. There's nothing to change.
  • The RTC token always has publish, publishAudio, publishVideo and publishData set to false.
  • The chat token always has MEMBER scope.
  • Sending an unknown field like role is rejected, not ignored.
  • The permissions are signed into the token, so the app can't widen them.

The only way to let someone broadcast is for your backend to call addHost for them.

Under the hood

These are normal RTC and Chat tokens. There's no third token type. In @livqeno/live, LiveStream.join() takes whatever your role's call returned.

Next steps