Expiring JWT tokens for live streams: private links that stop working
An expiring token turns a stream's watch address into a private link: the server signs a short statement saying which stream it is for, whether it allows watching or publishing, when it expires and whether only one viewer may use it, and refuses any request whose token is missing, altered or out of date. Add a revoke-all control and leaked links stop being a crisis.
What goes in the token
A JSON Web Token (JWT) is a small JSON payload plus a signature. For a live stream it typically carries:
- sub: the stream it applies to;
- use: play or publish;
- exp: when it expires;
- one-time: whether only the first viewer may use it.
The server signs it with a secret only it holds (HS256 is enough when the same server issues and checks). The payload is readable by anyone, so it must never contain anything secret.
Choosing the lifetime
- A ticketed event: valid for the event plus a margin, one viewer per link.
- An internal meeting: a few hours, shared freely within the company.
- Embedding on your own site: mint a fresh short-lived token per page view on your backend, so a copied link dies quickly.
Guest publish keys
The same mechanism works for sending. A token with use: publish lets a remote
guest or another venue's encoder go live on a stream without ever seeing the stream's own
key, and it stops working by itself.
Revoking everything
Expiry handles the normal case; revocation handles the leak. Storing one timestamp per stream and refusing every token issued before it gives a single button that kills all outstanding links and guest keys, while the owner's own key keeps working.
Mistakes that leak access
- Logging full URLs that contain tokens. Mask them in logs.
- Removing the token from a CDN cache key, so one viewer's cached response serves everyone.
- Very long lifetimes "to be safe", which turn a link into a permanent password.
In creekX: POST /streams/{id}/tokens with
{"use":"play","expiresInSeconds":7200,"oneTime":true} returns a signed JWT
and its watch path; "use":"publish" makes a guest key, and
POST /streams/{id}/tokens/revoke stops every token made so far. See the
API quick start and
how to secure live streams.
Frequently asked questions
Is a JWT encrypted?
No, only signed. Anyone can read what it says; nobody can change it without the server’s secret. Never put anything secret in the payload.
What happens when a token expires mid-stream?
New requests are refused. Whether an already-playing viewer is cut off depends on whether the server checks each request or only the start; check before relying on it.
Can a token be revoked before it expires?
Only if the server checks a revocation time. A common pattern is one revoke-all timestamp per stream: any token issued before it is refused.