Skip to main content
Version: v2.6.0

Signing Keys

Signing keys are used for accessing live streams with 'signed' playback policy.

Introduction to JWT Authentication

JSON Web Tokens (JWTs) are a widely recognized and a secure method for transferring information between two parties. Bitstreams utilizes JWTs to authenticate and authorize streaming requests, ensuring that your video content is securely delivered to the right users.

JWTs consist of three distinct parts: a header, a payload, and a signature. The header includes essential metadata for token decryption, the payload carries the configuration details, and the signature, created using a signing key pair, validates the token's authenticity. For a deeper understanding, visit jwt.io.

TermDefinition
Signing KeyA general term for any key used to sign data.
Private KeyA secret key used for signing data.
Key ID (kid)An identifier used to specify which key was used for signing in systems where multiple keys are present. It helps Bitstreams select the appropriate key for verification.

Example JWT

Full JWT format

Header.Payload.Signature

Header

{
"alg": "RS256",
"kid": "766a1e170aa5421aa539ab773cd2fb43",
"typ": "JWT"
}

Payload

{
"sub": "3YcwbTUyaGiXKtXpKADUAWbiQ8F9ci2EC1R9dYpj4zNBVFJpqUovD9o",
"aud": "v",
"exp": 1708457257
}

Signature

The signature will be a string, created in the following way:

HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)

Generating Signing Keys

To begin signing JWTs, generate a signing key. This key pair plays a crucial role in the cryptographic process of signing tokens, ensuring they are secure and verifiable. Signing keys can be conveniently created through the Bitstreams Settings Page

Streaming with JWTs

A JWT is added on to the streaming URL as shown below, {JWT} should be replaced with the real JWT string:

http://<server-ip>:80/live/<stream-key>.m3u8?token={JWT}
http://<server-ip>/live/<stream-key>.m3u8?token=eyJhbGciOiJSUzI1Ni...

Information Required for Creating JWTs

  • Live Stream playback ID
    • The playback ID can be found on the live stream session page.
  • Signing Key - ID
    • The signing key ID can be seen on the Settings page, under the Signing Key Tab.
    • It is the same ID that is shown when a new signing key is generated.
  • Signing Key - Private Key
    • The private key is shown when generating a new signing key, it must be downloaded or saved right away.
    • You cannot view the private key of existing signing keys in the Bitstreams dashboard.

Preparing for Production

When transitioning to a production environment and preparing to serve your customers, it's crucial to implement a secure and scalable method for signing JWTs. Below, you'll find tailored code samples to guide you in signing JWTs using GO and Python, ensuring a seamless and secure user experience.

Code Examples for JWT Signing

Python Example

import jwt
import base64
import time

# pip install pyjwt cryptography

# Enter stream playback id here
playback_id = '3VgWZGjhhC3S4UmGh2Cdqca7kyake1gyFAxHRf1DYu89nNaSpCCf3d7'

# Enter the signing key Id here
signing_key_id = 'cc78e4b95ea8407186e640401ed65d11'

# Enter the base64 encoded private key here
private_key_base64 = 'LS0tLS1CRUdJTiBSU0EgUF...'

private_key = base64.b64decode(private_key_base64)

# Preparing the payload
payload = {
'sub': playback_id,
'aud': 'v',
'exp': int(time.time()) + 3600, # 1 hour
}

# Including the 'kid' in the header
headers = {
'kid': signing_key_id
}

# Generating the JWT
json_web_token = jwt.encode(
payload, private_key, algorithm="RS256", headers=headers)

# Depending on your pyjwt version, json_web_token might be a byte string.
# If you need it as a string for display or further processing, you can decode it:
token_str = json_web_token.decode('utf-8') if isinstance(json_web_token, bytes) else json_web_token

print(token_str)

Go Example

package main

import (
"encoding/base64"
"fmt"
"log"
"time"

"github.com/golang-jwt/jwt/v4"
)

func main() {

// Enter the id for which you would like to get counts here
playbackId := "3VgWZGjhhC3S4UmGh2Cdqca7kyake1gyFAxHRf1DYu89nNaSpCCf3d7"

// Enter the type of ID provided in my_id; one of video_id | asset_id | playback_id | live_stream_id
myIdType := "v"

// Enter the Signing Key Id here
keyId := "cc78e4b95ea8407186e640401ed65d11"

// Enter the base64 encoded private key here
privateKey := "LS0tLS1CRUdJTiBSU0EgUF..."

decodedKey, err := base64.StdEncoding.DecodeString(privateKey)
if err != nil {
log.Fatalf("Could not base64 decode private key: %v", err)
}

signKey, err := jwt.ParseRSAPrivateKeyFromPEM(decodedKey)
if err != nil {
log.Fatalf("Could not parse RSA private key: %v", err)
}

// Preparing a new token with the claims
token := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.MapClaims{
"sub": playbackId,
"aud": myIdType,
"exp": time.Now().Add(time.Minute * 15).Unix(), // 15 Minutes
})

// Setting the 'kid' in the header, not in the payload
token.Header["kid"] = keyId

// Generating the signed token string
tokenString, err := token.SignedString(signKey)
if err != nil {
log.Fatalf("Could not generate token: %v", err)
}

fmt.Println(tokenString)
}