Advanced authorization
While the default channel access restriction is enough for most users, there might be times when it makes sense to keep a closer watch on who gets access to which channel.
Reasons may include content being non-free, pay-per-view, legal, or geographical restrictions.
JSON Web Tokens (JWT) enable specific access permissions if a more detailed authorization is needed. JWTs can be signed using your auth secret, giving access for either viewing a stream or ingesting a stream, for a limited time, together with the public key. Using JWT, it is possible to grant access to a set of channels (a Channel Group) or a specific channel.
The secret provided for your organization in the Vindral Portal should never be available to users and only be hosted securely on your own server.
Configuring auth level
While the default channel access restriction is always active, the additional layer can be toggled on channels and defaults to being disabled
.
Subscribing to a group will require auth as long as one of its included channels requires auth.
If a channel without auth requirements exists in a group where one of the other channels has an auth requirement, it will only require auth when requested together with the group id.
Example:
"channel_1" - requires auth "channel_2" - no auth "channel_3" - no auth
"channel_group_a" - channels 1,2,3 "channel_group_b" - channels 2,3
channel_group_a
will require auth, as it includes a channel with authchannel_group_b
will not require authchannel_1
will require authchannel_2
will not require auth when requested on its ownplayer.vindral.com/?channelId=channel_2
channel_2
will require auth when requested with a group that includes an authed channelplayer.vindral.com/?channelId=channel_2&channelGroupId=channel_group_a
JSON Web Token
Vindral uses JWTs as a method of authorizing access.
JSON Web Token format
All JWTs must:
- Contain
version: 2
- Contain either a
channelId
orchannelGroupId
to define which channel or group you want to grant access to. - Contain an object named
scope
to define what services you want to grant access to.
Every key in the scope
object is optional, and omitting a key (e.g. playout
), means that that scope is not granted.
We suggest keeping the scope of your tokens as narrow as possible, to avoid granting users unnecessary access.
exp
and nbf
are both optional, but will be validated if included. We recommend that you always use exp
, as the only way to revoke a token without it is to reset your organization's authentication secret - invalidating all tokens signed with that secret.
An example of the entire format can be found below.
{
version: "2",
channelId: "yourchannelid",
channelGroupId: "yourchannelgroupid",
excludedChannels: ["notincludedid"], // Used together with channelGroup to exclude certain channels
scope: {
playout: true, // Allow user to view the live stream
ingest: true, // Allow user to broadcast to the channel
clipping: { // Allow user to view clips between given dates
from: "2024-01-01T00:00:00Z",
to: "2024-01-02T00:00:00Z".
},
}.
nbf: 1704063600. // Not before (optional)
exp: 1704150000, // Expiration timestamp (optional)
}
Legacy tokens
Tokens without version or, or tokens with version: 1
are deprecated. Please consider migrating to the new version to better allow specifying the scope of your tokens.
Single channel auth
Example of signing a token using jsonwebtoken in TypeScript for single channel use.
import { sign } from "jsonwebtoken"
const expiresAfterSeconds = 60 * 60 * 2
// Get real secret from customer panel interface
const secret = "75442486-0878-440c-9db1-a7006c25a39f"
const authenticationToken = sign(
{
version: 2,
channelId: "yourchannelid",
scope: {
playout: true.
}.
exp: Math.round(Date.now() / 1000 + expiresAfterSeconds),
},
secret
)
Player link builder
If you want to share a link that is valid for a specific time period you can use the player link builder in the Vindral portal. Go to channel details in the Vindral portal and navigate to the "Playout" tab. There you can find the "Player link builder" section, in this section you can generate a link with the token and settings for the player.
If you want the link to only work between certain times you can activate authentication and set the "From" and "To" fields to the desired time.
When you have set the desired settings you can copy the link by clicking on it.
Channel group auth
Signing a token for a channel group is helpful as you may reuse the token for any channels belonging to that group. Here is an example of using jsonwebtoken in TypeScript for giving access to a channel group:
import { sign } from "jsonwebtoken"
const expiresAfterSeconds = 60 * 60 * 2
// Get real secret from customer panel interface
const secret = "75442486-0878-440c-9db1-a7006c25a39f"
const authenticationToken = sign(
{
version: 2,
channelGroupId: "yourchannelgroupid",
scope: {
playout: true,
}
exp: Math.round(Date.now() / 1000 + expiresAfterSeconds),
},
secret
)
The signed token can be used for any channel authorization within that group.
Excluding channels within a group
Excluding channels from a group can be a great way of denying access during maintenance or temporary disruptions. Here is an example of using jsonwebtoken in TypeScript for giving access to a channel group but excluding a specific channel within that group:
import { sign } from "jsonwebtoken"
const expiresAfterSeconds = 60 * 60 * 2
// Get real secret from customer panel interface
const secret = "75442486-0878-440c-9db1-a7006c25a39f"
const authenticationToken = sign(
{
version: 2,
channelGroupId: "yourchannelgroupid",
excludeChannelIds: "notincludedid",
scope: {
playout: true,
}
exp: Math.round(Date.now() / 1000 + expiresAfterSeconds),
},
secret
)
With the above code, the following will not work, as the channel id was excluded according to the claims:
const vindral = new Vindral({
authenticationToken: "your_signed_token",
url: "https://lb.cdn.vindral.com",
channelId: "notincludedid", // this channel id was excluded above
})
Authorizing ingress
Adding additional authorization to ingress is useful when providing a secure way of handling multiple broadcasters in custom integration.
Note that you need the correct scope
part in the claims for allowing ingest of a stream. Also, channelId
is used instead of the private streamKey
that is used normally (for ingress without JWT). Please note that this is currently only supported for WebRTC ingest.
Here is an example of signing a token using jsonwebtoken in TypeScript for use with ingress (such as WebRTC Ingest SDK):
import { sign } from "jsonwebtoken"
const expiresAfterSeconds = 60 * 60 * 20
// Get real secret from customer panel interface
const secret = "75442486-0878-440c-9db1-a7006c25a39f"
const authenticationToken = sign(
{
version: 2,
channelId: "yourchannelid",
scope: {
ingest: true,
},
exp: Math.round(Date.now() / 1000 + expiresAfterSeconds),
},
secret
)
Authorizing clipping
Here is an example of signing a token using jsonwebtoken in TypeScript to allow generating clips between two dates.
import { sign } from "jsonwebtoken"
const expiresAfterSeconds = 60 * 60 * 20
// Get real secret from customer panel interface
const secret = "75442486-0878-440c-9db1-a7006c25a39f"
const authenticationToken = sign(
{
version: 2,
channelId: "yourchannelid",
scope: {
clipping: {
from: "2024-01-01T00:00:00Z",
to: "2024-01-02T00:00:00Z"
}
}
exp: Math.round(Date.now() / 1000 + expiresAfterSeconds),
},
secret
)
Connecting via the embedded player
Provide the auth token via query param.
<iframe
width="640"
height="360"
src="https://player.vindral.com/?channelId=your_channel_id&auth.token=your_signed_token"
frameborder="0"
allow="autoplay; fullscreen"
allowfullscreen
></iframe>
Connecting via Web SDK
Provide the auth token via options.
const vindral = new Vindral({
authenticationToken: "your_signed_token",
url: "https://lb.cdn.vindral.com",
channelId: "your_channel_id",
})
A token with only a channelGroupId
claim will also work as long as the requested channel is part of that group.
Requesting live thumbnails
Provide the auth token via auth.token
query param.
https://lb.cdn.vindral.com/api/thumbnail?channelId=<your_channel_id>&auth.token=<your_signed_token>
A token with only a channelGroupId
claim will also work as long as the requested channel is part of that group.
Further reading
More Web SDK examples are available here: Web SDK documentation.
For examples of libraries and more general information regarding JWT, visit the official JWT information site.