Last Updated: October 21, 2019
JW Player enables you to create expiring, signed URLs to secure your content and player. Using signed URLs for your public content or player prevents unauthorized viewers from downloading your content or embedding your player on sites that you do not own.
To enable URL signing on your media content and players, you must complete two general processes:
- Create signed (non-JWT or JWT) URLs.
- Enable URL signing functionality
Before explaining how to implement URL signing, the next section explains the types of signed URLs that JW Player supports.
Types of signed URLs
JW Player's Delivery API supports two methods of signing URLs:
- Signed non-JWT (non-JWT)
- JSON web token (JWT) tokenized
Non-JWT URLs apply when you reference any of JW Player's v1 endpoints and routes. JWT URLs apply when you reference any of the JW Player's v2 endpoints and routes.
The following table identifies when to use each type of signed URL.
Signed URL type | Applicable routes |
---|---|
non-JWT | Players* • /libraries/player_id.js • /players/content_id-player_id.embed_type • /previews/content_id-player_id.html Poster image • /thumbs/media_id-thumb_width.jpg Streaming manifests • /manifests/media_id.manifest_extension Text tracks • /tracks/track_id.track_extension Video files • /videos/media_id-template_id.media_extension |
JWT | Advertising schedule* • /v2/advertising/schedules/ad_schedule_id.ad_schedule_extension Media (This includes streaming manifests, text tracks, and video files) • /v2/media/media_id Playlist • /v2/playlists/playlist_id Poster image • /v2/media/media_id/poster.jpg |
* Denotes content that can be accessed only through this route of the Delivery API.
Create a signed non-JWT URL
To create a non-JWT URL, you must append two parameters to the URL of the content or player: exp
and sig
.
http://cdn.jwplayer.com/videos/nPripu9l.mp4?exp=1371335018&sig=a0124258c73177029d09bb82c6608392
Parameter | Description |
---|---|
exp | Expiration date of the URL as a UNIX timestamp, for example, 1271338236 Typically, generated URLs should be valid between a minute and a few hours. |
sig | Signature used to authorize the request See: sig parameter. |
sig parameter
The signature (sig
) is an MD5 digest of the path, the expiration date, and the account secret: md5(CONTENT_PATH:EXPIRATION_STAMP:ACCOUNT_SECRET)
.
Parameter | Description |
---|---|
ACCOUNT_SECRET | Property secret Use the following steps to locate your property secret: 1. From your JW Player dashboard, click the gear next to your name > API Credentials. 2. In the JW Platform API Credentials section, click SHOW CREDENTIALS next to a property name. 3. Copy the Secret. |
CONTENT_PATH | Only the path portion of the URL without the domain or leading slash, for example, videos/nPripu9l.mp4 |
EXPIRATION_STAMP | Expiration date of the URL as a UNIX timestamp, for example, 1271338236 |
Generate the non-JWT signed URL
The following code examples show approaches to programmatically generate a non-JWT signed URL.
IMPORTANT
The following samples are provided for guidance and may not work in your environment. If you use any of these samples, be sure to test the functionality in a development environment before deploying it into a production environment.
<?php
function get_signed_player($videokey,$playerkey) {
$path = "players/".$videokey."-".$playerkey.".js";
$expires = round((time()+3600)/300)*300;
$secret = "Ksi93hsy38sjKfha9JaheEMp";
$signature = md5($path.':'.$expires.':'.$secret);
$url = 'http://cdn.jwplayer.com/'.$path.'?exp='.$expires.'&sig='.$signature;
return $url;
};
echo "<p>Watch this cool video:</p>";
echo "<script type='text/javascript' src='".get_signed_player('nPripu9l','ALJ3XQCI')."'></script>";
?>
import time
import hashlib
def get_signed_player(video_key, player_key):
path = "players/{video_key}-{player_key}.js".format(
video_key=video_key, player_key=player_key
)
expires = round((time.time() + 3600) / 300) * 300
secret = "INSERT SECRET HERE"
signature = hashlib.md5(
"path:{exp}:{secret}".format(exp=str(expires), secret=secret)
)
url = "http://cdn.jwplayer.com/{path}?exp={exp}&sig={sig}".format(
path=path, exp=str(expires), sig=signature.hexdigest()
)
return url
video_key = "nPripu9l" # example video key
player_key = "ALJ3XQCI" # example player key
signed_url = get_signed_player(video_key, player_key)
print("<p>Watch this cool video:</p>")
print(
"<script type='text/javascript' src='{signed_url}'></script>".format(
signed_url=signed_url
)
)
Create a signed JWT URL
To create a JWT URL, you must append a token
parameter to the URL of the content or player. The token parameter is comprised of three Base64-URL strings separated by dots that can be easily passed in HTML and HTTP environments.
To generate the token
parameter you need a header, payload, and signature. The next three subsections define the header, payload, and signature. Then, the Generate the JWT signed URL subsection provides code examples to generate the JWT signed URL.
Header
The header specifies the cryptographic algorithm and token type. JW Player currently supports a single algorithm and token type. All headers should use the following:
{
"alg": "HS256",
"typ": "JWT"
}
Property | Type | Description |
---|---|---|
alg | String | (Required) Signing algorithm used This is always HMAC SHA256 ( HS256 ). |
typ | String | (Required) Type of token This is always JWT . |
Payload
The payload consists of claims that specify a resource (resource
) being requested, an expiration time (exp
), and any parameters the route accepts. The following code example includes related_media_id
as an additional parameter.
The resource
and exp
properties are required.
{
"resource": "/v2/playlists/Xw0oaD4q",
"exp": 1893456000,
"related_media_id": "RltV8MtT"
}
Property | Type | Description |
---|---|---|
exp | Number | (Required) Expiration date of the token, as a UNIX timestamp Generated URLs should be valid between a minute and a few hours. The shorter you make the duration until an expiration date, the more secure you make your content. Once a link has expired, even download tools will not be able to grab the content. However, overly short expirations can result in bad user experience due to small discrepancies in server time or delays in clients requesting resources. If you have a high-volume website, you should cache signed URLs (for example in intervals of 5 minutes) to prevent performance issues that may occur due to generating signed URLs. Signed requests do not have to be unique. |
resource | String | (Required) Content or player that is being requested This can be a relative or absolute URL. This property ensures that generated tokens cannot be applied to unintended resources. |
Signature
The signature is comprised of the encoded header, the encoded payload, and the property secret.
Use the following steps to locate your property secret:
- From your JW Player dashboard, click the gear next to your name > API Credentials.
- In the JW Platform API Credentials section, click SHOW CREDENTIALS next to a property name.
3, Copy the Secret.
Generate the JWT signed URL
The following code examples show approaches to programmatically generate a JWT signed URL.
IMPORTANT:
The following samples are provided for guidance and may not work in your environment. If you use any of these samples, be sure to test the functionality in a development environment before deploying it into a production environment.
<?php
require_once('JWT.php'); // Available from https://github.com/firebase/php-jwt/blob/master/src/JWT.php
use \Firebase\JWT\JWT;
$playlist_id = "myListID"; // Replace with your playlist ID
$token_secret = "myAPIsecret"; // Replace this value with the API secret for the property
$resource = "/v2/playlists/".$playlist_id;
$exp = ceil((time() + 3600)/180) * 180; // Link is valid for 1hr but normalized to 3 minutes to promote better caching
$token_body = array(
"resource" => $resource,
// Other request parameters can be added here if desired.
"exp" => $exp
);
$jwt = JWT::encode($token_body, $token_secret);
print "<a href=\"https://cdn.jwplayer.com/$resource?token=$jwt\">This is a signed link.</a>";
from jose import jwt
import math
import time
def jwt_sign_url(path, host='http://cdn.jwplayer.com/'):
secret = '12345'
exp = math.ceil((time.time() + 3600)/180) * 180 # Link is valid for 1hr but normalized to 3 minutes to promote better caching
token_body = {
"resource": path,
# Other request parameters can be added here if desired.
"exp": exp
}
url = '{host}?sig={signature}'.format(host=host, signature=jwt.encode(token_body, secret, algorithm='HS256'))
return url
Enable URL signing functionality
After you have created signed URLs for all of your content, you must enable URL signing functionality for your properties.
- From the Properties page of your dashboard, click the name or settings icon of the property. The Property Settings page appears.
- On the General tab in the URL Signing section, click the toggle to Secure Video URLs or Secure Player Embeds. Depending on your use case, you can also enable both settings at the same time.
- Click SAVE.
Error handling
Error code | Error message | Posible conditions |
---|---|---|
200 | 200 Success | Content is requested via a signed URL when URL signing is enabled for all publisher content. |
403 | 403 Access forbidden | Content is requested via an unsigned URL when URL signing is enabled for all publisher content. Content is requested via an incorrectly signed URL when URL signing is enabled for all publisher content. |