Sign Playback URLs with a Token

Require a signed token on playback URLs, encrypt query strings, and manage the application keys used to sign them.

Sign Playback URLs with a Token

Control how and when content is consumed by including an HMAC token that signs your playback URL. By default, an asset, live channel, or live event requires a digital signature before playback. This digital signature must be appended to the playback URL's query string. Upon requesting playback, the system validates that the playback window has not expired and that the playback URL and query string have not been tampered with. Playback is allowed only after the digital signature has been validated.

Determine whether playback URLs must be signed

  1. From the CMS, perform one of the following:

    • Asset: Select the desired asset from the Content tab and then select the Playback tab.
    • Live Channel: Select the desired live channel from the Live Channels tab and then select the Playback tab.
    • Live Event: Open the desired live event from the Live Events page and then select the Config tab.
  2. Toggle the state of the Require a token for playback option to determine whether the playback URL must be signed.

  3. Select Save.

Exceptions

The system automatically hosts a playback page and signs playback URLs under the following circumstances:

  • Test players
  • HTML embed code

Key information:

  • Take care when distributing or sharing test players or HTML embed code. Either one may be used to play your content without restrictions. Playback via HTML embed code may be restricted to specific domains via the Allowed Domains option. Test players are designed to facilitate testing and demos.

  • A test player may be invalidated by selecting the icon that appears next to it, while HTML embed code may be expired by selecting Expire. Upon saving your changes, a new test player or HTML embed code may be automatically generated.

    Prevent test players from being automatically generated by marking the Enable option under the Prevent Auto Creating Test Players section of the Test Player Restrictions page.

Basic Setup

Most programming languages only require a few lines of code to sign a playback URL.

Define what will be signed and the digital signature through the following query string parameters:

  • Core identification parameters: Include these required parameters to identify playback content, its owner, and the playback window.

  • Customization parameters: Include these optional parameters to customize how content playback is handled.

  • Signature parameter: Append the sig parameter to the end of the query string to digitally sign the playback URL based on the specified core identification and customization parameters.

Syntax:
{Playback URL}?{Core Identification Parameters}&{Optional Customization Parameters}&sig={Signature}

Example:
https://content.uplynk.com/ext/aaaaaaa/my_asset.m3u8?tc=1&exp=1530561660&rn=411...48&ct=a&cid=ea10...c38&sig=37e...cbf

Core Identification Parameters

The following core identification parameters must be specified:

ParameterDescriptionExample
tcIdentifies the token check algorithm version. Set this parameter to 1.tc=1
expDetermines when, in Unix time, this signed playback URL expires. Digital signatures should have a short lifespan. However, they should not expire less than 10 seconds after being issued.exp=1530316768
rnDefines a random number that increases the uniqueness of the signature.rn=4114845747
ctIdentifies the type of content that will be played back. Valid values are: a for Asset, c for Live channel, e for Live event, p for Virtual linear playlist (including Smartstart-enabled assets).ct=a
cidIdentifies an asset, channel, live event, or virtual linear playlist via one of the following methods:
- System-defined ID (GUID): Set the cid parameter to an asset ID, channel ID, event ID, or playlist ID.
- External ID: Set both eid and oid parameters.
cid=ea10fa402fec4bbe996019a0827e6c38
eid & oidExternal ID:
- eid: Set this parameter to the external ID for the desired asset, live channel, or live event.
- oid: Set this parameter to your user ID. Specify your own user ID regardless of whether the content resides in your CMS library or one shared with you. User IDs defined within the actual playback URL for content in a shared library should still identify the user that shared the content with you. Find your user ID via User Settings > Settings > User Settings.
...&eid=puppycampaign1234&oid=
ab233951a92b88a1a123cdd49b0a9be5
Core Identification Parameter Examples

Asset ID Example:

This example defines core identification parameters using an asset ID:

ConditionDetailsValue
Current TimeA signed playback URL should expire relatively quickly. Therefore, it is important to know the time, in UTC, at which it will be issued.
Local timeJuly 02, 2018 01:00:00 p.m. PST
Coordinated Universal TimeJuly 02, 2018 20:00:00 UTC
Unix time (UTC)1530561600
Desired LifespanAdd the desired lifespan to the current Unix time. Adding 60 seconds to 1530561600 results in the following value: 153056166060 seconds
Random NumberA random number ensures the uniqueness of the digital signature that is generated.4114845747
CMS AssetThis example authorizes the playback of a CMS asset. Identify this asset by its asset ID.ea10fa402fec4bbe996019a0827e6c38

Using the above values, construct the core identification portion of the query string:

tc=1&exp=1530561660&rn=4114845747&ct=a&cid=ea10fa402fec4bbe996019a0827e6c38

External ID Example:

An alternative method for identifying playback content is via its external ID. This requires omitting the cid parameter and defining both the eid (external ID) and oid (Workspace ID) parameters. This example builds off the previous example, but uses the following information instead of the asset ID:

ConditionValue
CMS Asset
This example authorizes the playback of a CMS asset. Identify this asset by its external ID.
External IDs must be unique within your account.
Your CMS asset may be assigned an external ID that is a duplicate to one associated with another customer. For this reason, you must also specify your Workspace ID when identifying an asset by its external ID.
External ID:
widgets-sales-conference-01
Workspace ID
Specify your Workspace ID to uniquely identify your asset.
Workspace ID:
ab233951a92b88a1a123cdd49b0a9be5

Using the above values, construct the core identification portion of the query string:

tc=1&exp=1530561660&rn=4114845747&ct=a&eid=widgets-sales-conference-01&oid=ab233951a92b88a1a123cdd49b0a9be5

Digital Signature

A digital signature protects the playback URL against tampering by allowing the system to validate the playback URL's query string against a hashed version of it.

Key Information:

  • Generate a hash-based message authentication code (HMAC) under the following conditions:

    • Algorithm: SHA-256
    • Secret Cryptographic Key: Your API key (Integration Keys page > Settings > Integration Keys > API Keys)
  • Data: All core identification and customization query string parameters defined in the playback URL. Do not include the question mark that delimits the base URL from the query string.

    📘

    Use a server-side script to generate an HMAC. Otherwise, your API key will be exposed and potentially allow your content to be played back without restrictions.

  • Set the sig parameter to the hashed message generated for the current playback URL and then append it to the query string. The sig query string parameter must be the final parameter in the playback URL's query string.

View a sample digital signature
This example signs a playback URL under the following conditions:

  • Core identification parameters:
    tc=1&exp=1358341863&rn=4114845747&ct=a&cid=ea10fa402fec4bbe996019a0827e6c38

  • Customization parameter: ray=abc

    This parameter restricts playback to rays A, B, and C.

  • API key: WxQpQhHFmE4hTWA4TGLu6rYeNuKgYrWwlCLmSKRb

The following HMAC is computed from the above query string using the SHA-256 algorithm and the above API key as the secret cryptographic key:

37ecd4cbcad4bc156daac10a2bf9ccf38fb7a8d83fa25f257a62474a86b82cbf

Set the sig parameter to the above value and append it to the query string as shown below.

tc=1&exp=1358341863&rn=4114845747&ct=a&cid=ea1...c38&ray=abc&sig=37e...cbf

Finally, set the above value as the query string for the playback URL.

Sample playback URL:

https://content.uplynk.com/ea10fa402fec4bbe996019a0827e6c38.m3u8?tc=1&exp=1358341863&rn=4114845747&ct=a&cid=ea10fa402fec4bbe996019a0827e6c38&ray=abc&sig=37ecd4cbcad4bc156daac10a2bf9ccf38fb7a8d83fa25f257a62474a86b82cbf

Sample Code

Sample code that signs a playback URL is provided below.

import hashlib, time, hmac, urllib.parse, random

# Update to your API key.
apiKey = 'WxQpQhHFmE4hTWA4TGLu6rYeNuKgYrWwlCLmSKRb'

# Set to all of the playback URL's query string parameters except the signature.
queryStr = urllib.parse.urlencode({
    'tc': '1', # token check algorithm version
    'exp': int(time.time()) + 60, # expire 60 seconds from now
    'rn': str(random.randint(0, 2**32)), # random number
    'ct': 'a', # an asset
    'cid': 'ea10fa402fec4bbe996019a0827e6c38', # the asset's ID
    'rays': 'dcba', # customization parameter
})

# Compute the signature and add it to the *end*
sig = hmac.new(apiKey.encode('utf-8'), queryStr.encode('utf-8'), hashlib.sha256).hexdigest()

queryStr = queryStr + '&sig=' + sig

# Add the query string to the playback URL.
url = 'https://content.uplynk.com/ea10fa402fec4bbe996019a0827e6c38.m3u8'
url = url + '?' + queryStr
<?php
// inputs
$apiKey = "WxQpQhHFmE4hTWA4TGLu6rYeNuKgYrWwlCLmSKRb"; // from the CMS UI

// combine all of the parameters
$msg = array();
$msg["tc"] = "1"; // token check algorithm version
$msg["exp"] = time() + 60; // expire 60 seconds from now
$msg["rn"] = rand(); // random number
$msg["ct"] = "a"; // an asset
$msg["cid"] = "ea10fa402fec4bbe996019a0827e6c38"; // asset ID
$msg["rays"] = "dcba"; //customization parameter

// Calculate signature
$msg["sig"] = hash_hmac("sha256", http_build_query($msg), $apiKey);

// Add the query string the playback URL.
$url = 'https://content.uplynk.com/ea10fa402fec4bbe996019a0827e6c38.m3u8';
return $url . '?' . http_build_query($msg);

These are complete Python scripts for signing an Uplynk playback URL (e.g. creating a token), using the asset ID URL format and the External ID URL format:

Encrypt Query Strings

A playback URL may be passed as either cleartext or encrypted text. Encrypting query strings is useful for masking keywords (e.g., ad) that may trigger an ad blocker.

  1. Generate a Query String Value that signs your playback URL.

  2. Copy an API Key. Find your API key via Integration Keys page > Settings > Integration Keys > API Keys.

  3. Generate an MD5 Hash of your chosen API key. This hash should be exactly 16 bytes (128 bits) long.

  4. Encrypt the Query String:

    • Use AES-128 in CBC mode for encryption.
    • Use the MD5 hash as the key for this operation.
    • Use 16 null bytes as the initialization vector.
  5. Base64 Encode the Encrypted Result:

    • Perform URL-safe Base64-encoding on the encrypted result.
    • This typically involves replacing all + characters with - and all / characters with _. Some languages and libraries have URL-safe-specific functions for this purpose.
  6. Set the Playback URL's Query String:

    • Syntax:

      ?cqs=Base64EncodedQueryString&kid=APIKeyID
    • API keys and their IDs are listed next to each other within the CMS.

    • If a playback URL contains both cqs and kid parameters, the system will:

      • Decrypt the value assigned to cqs using the API key identified by the kid parameter.
      • Establish a normal playback session using the information from the decrypted string.

Sample Code

Sample code that encrypts query strings is provided below.

import base64
import hashlib

from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives.padding import PKCS7
from cryptography.hazmat.backends import default_backend

API_KEY = b'cL8Z0+DHCJZqpsN6/tlB01oyxFfeElj3t7PnwWRI'
KEY_ID = 'ad5ba943177f4a1587795a9ee8d47293'

MD5_KEY = hashlib.md5(API_KEY).digest()

# This query string is signed for an asset with an asset ID of 340ca73eb07c4f4ca08b804c47a91f1b,
# owned by a user with a Workspace ID of ba8cb548202840d48d1255885d7bb2f3
SIGNED_QUERY_STRING = b'ad=fwvod&cid=340ca73eb07c4f4ca08b804c47a91f1b&oid=ba8cb548202840d48d1255885d7bb2f3&exp=1492596978713&test=1&rn=310292100&tc=1&ct=a&sig=2ff94739b021912712adafeccd6fa291f11eef0648c3b18b30224b84e0590b4f'

def encrypt_aes_128_cbc(key, data):
    backend = default_backend()
    aes = algorithms.AES(key)
    iv = b'\x00' * 16  # Initialization vector of 16 null bytes
    cbc = modes.CBC(iv)
    padder = PKCS7(aes.block_size).padder()
    padded_data = padder.update(data) + padder.finalize()

    encryptor = Cipher(aes, cbc, backend).encryptor()
    result = encryptor.update(padded_data) + encryptor.finalize()
    return result

# Encrypt the query string using the MD5 hash of the selected API key
crypted_qs = encrypt_aes_128_cbc(MD5_KEY, SIGNED_QUERY_STRING)

# Encode the encryption result as URL-safe base64
encoded_qs = base64.urlsafe_b64encode(crypted_qs).decode("utf-8")

new_params = {'cqs': encoded_qs, 'kid': KEY_ID}

# This will be the new playback URL to request from our system.
url_with_crypted_qs = 'https://content.uplynk.com/340ca73eb07c4f4ca08b804c47a91f1b.m3u8?cqs={cqs}&kid={kid}'.format(**new_params)

print(url_with_crypted_qs)

### Value of `url_with_crypted_qs` is:
### https://content.uplynk.com/340ca73eb07c4f4ca08b804c47a91f1b.m3u8?cqs=gYXTAVtWRvk0qCs8pM9CmgprLvyQt9jNDETBL4ApLCqf2iFh-c9tXSk2Q_EbAAFc4q19KTikvqx8-StlruVaLafXU2NciESn-ZNPa-thp8UXSWwKszIp8oBjx8SJr9fcwUmu9El-w2q9lQ61nu1pk1JxomEraZAtfie9k8f5vAklpyYg5Ejd6i7iokxFO1XflOJFkhnDHp1ozCXVgh-rYKuCbbOEUwAaGYgd4zjn88GBgO1ZY8Jn3OFyGssvOydsPAnRjQmPsfFE24wYsp1Mlg==&kid=ad5ba943177f4a1587795a9ee8d47293

Application Keys

An application key provides an additional layer of security when transferring content keys to an application (e.g., media player).

To Set Up Application Key Support

  1. Add an Application Key:

    • Navigate to the Integration Keys page.
    • Go to the Application Keys section.
    • In the Key Name option, assign a name to the application key.
    • Select + Add to generate a value for the application key.
  2. Update Your Application:

    • Pass the application key to the client SDK.
    • Although application keys are displayed in the CMS as a string value, they should be treated as binary data. For example, if the CMS shows an application key of "88051e9b", the actual value is the following sequence of bytes: 0x88 0x05 0x1E 0x9B. Take steps to protect your application against reverse engineering.
  3. Enable Application Keys:

    • Include the ak configuration parameter in the playback URL's query string.
    • Upon including this parameter, the signed playback URL will only work with an application key.
  4. Modify the Playback URL: Change the file extension defined in the playback URL from "m3u8" to "json".

    Sample Playback URL: https://content.uplynk.com/channel/ext/8bb3fcf33d134160848b3051fa15ea21/live_feed_east.json?tok=...

How It Works

Upon receiving a playback request, the system transfers a content key to the media player over a secure HTTPS connection. Use an application key, which is a secret key embedded in a device or application, to apply an additional layer of encryption when transferring a content key.

📘

Application keys require an application that leverages our client SDK.

📘

Application keys require client-side functionality and therefore cannot be used for web-based playback.


Did this page help you?