Skip to content

License Token Tutorial

This document provides step-by-step instructions on how to generate tokens for the token-based license issuance, along with sample code.

Before you read this tutorial, please keep the following points in mind:

  • The creation of the token must be performed on the Content Management System (CMS) back-end server of the content service to which DoveRunner Multi-DRM will be applied.
  • Generating tokens directly from within client-side JavaScript or mobile applications is a security risk and should be avoided.
  • Before playing the DRM content on the client player, the CMS backend must determine whether the client or user is authorized to play. Then it generates a token with DRM license rules (time limit and security options) and pass it to the client.
  • The function of delivering the token data to the client should be implemented by the content service. Usually it is transmitted with the metadata (playback URL, DRM linked data, poster image, etc.) of the DRM contents to be played.
  • The sample code in this document is based on Node.JS. If you use any other server-side programming language, please refer to the sample code and implement the converted code yourself.
  • The various setting values shown in the sample code are for reference only. The generated token data in the sample code does not actually work.
  • To create a working token, you need to enter the setting value of your account after signing up to DoveRunner service.

The step-by-step example code below can be run in a NodeJS application or in an online NodeJS IDE like JDoodle.

Prepare various input values required for license token generation as follows.

const AES_IV = "0123456789abcdef";
const siteInfo = {
"siteId": "TUTO",
"siteKey": "lU5D8s3PWoLls3PWFWkClULlFWk5D8oC",
"accessKey": "LT2FVJDp2Xr018zf4Di6lzvNOv3DKP20"
};
let licenseInfo = {
"drmType": "Widevine",
"contentId": "bigbuckbunny",
"userId": "test-user"
};
let licensePolicy = {
"policy_version": 2,
"playback_policy": {
"persistent": false
}
};
console.log("license policy : " + JSON.stringify(licensePolicy));
NameFormatDescription
AES_IV16 bytes string”0123456789abcdef” (fixed value)
siteId4 uppercase alphabetThe ID of the service site registered on DoveRunner Console site (check the DoveRunner Console’s ‘Site Settings’ page)
siteKey32 bytes base64 stringEncryption key required for service site integration (check the DoveRunner Console’s ‘Site Settings’ page)
accessKey32 bytes base64 stringEncryption key used for additional integration such as packager, license token, etc. (check the DoveRunner Console’s ‘Site Settings’ page)
drmTypeInput one of these DRM. “NCG”, “Widevine”, “PlayReady”, “FairPlay” (case sensitive)Enter the type of DRM corresponding to the client environment. Refer to DRM Platform Support
contentIdMax 200 alphanumeric charactersThe unique ID of the DRM content to play. Must be the same as the CID used to package the content.
userIdMax 32 alphanumeric charactersEnd-user’s ID which is managed by the content service. Input “LICENSETOKEN” if there is no user ID.

Value of drmType should be entered exactly in case according to the specification.

LicensePolicy JSON data is used to set the detailed policy for the content playback rights. This tutorial uses the default values as entered in the sample code above.

When you run Step 1 code, the following results are output to the browser console.

Terminal window
license policy : {"policy_version":2,playback_policy:{persistent:false}}

Encrypt the license rules JSON string prepared in step 1 with AES256 algorithm and convert the result to a base64 string.

// Add the following code after step 1 code
const crypto = require("crypto");
const cipher = crypto.createCipheriv("aes-256-cbc", siteInfo.siteKey, AES_IV);
let encryptedPolicy = cipher.update(
JSON.stringify(licensePolicy),
"utf-8",
"base64"
);
encryptedPolicy += cipher.final("base64");
console.log("encrypted policy : " + encryptedPolicy);

The following settings are used for AES encryption:

  • Encryption algorithm: AES256 CBC mode
  • Encryption key: The 32-byte DoveRunner site key value entered in step 1
  • IV (Initial Vector): 16 byte AES_IV value entered in Step 1
  • Padding: pkcs7 (not shown in the above code because it is default)

AES encryption processing must use the appropriate libraries and APIs for each server-side programming language.

The execution result of the second stage code is as follows.

Terminal window
encrypted policy : sX7DEMZ1S2xaMoIt76m+yDwylZRVJ2Gzs2I1b0+mzL0X9FcJ43aAloqI5noG2iyC57AagPl2jY9mxCL/WqNabQ==

The hash value used to verify the integrity of the token data is generated as follows:

// Add the following code after step 2 code
const UTCTime = new Date().toISOString().replace(/\.\d{3}/gi, '');
let hashData = {
siteId: siteInfo.siteId,
accessKey: siteInfo.accessKey,
drmType: licenseInfo.drmType,
userId: licenseInfo.userId,
cid: licenseInfo.contentId,
policy: encryptedPolicy,
timestamp: UTCTime
};
const hashInput =
hashData.accessKey +
hashData.drmType +
hashData.siteId +
hashData.userId +
hashData.cid +
hashData.policy +
hashData.timestamp;
console.log("hash input : " + hashInput);
let hashString = crypto
.createHash("sha256")
.update(hashInput)
.digest("base64");
console.log("hash string : " + hashString);

The input value for generating a hash is a string of various configuration values, encrypted license rules, and current time information according to token specification.

The SHA256 algorithm is used to generate hash values, and the resulting value of the hash function must be entered into the base64 function as a binary data, without being converted to a string.

The result of the execution of Step 3 code is as follows.

Terminal window
hash input : LT2FVJDp2Xr018zf4Di6lzvNOv3DKP20WidevineTUTOtest-userbigbuckbunnysX7DEMZ1S2xaMoIt76m+yDwylZRVJ2Gzs2I1b0+mzL0X9FcJ43aAloqI5noG2iyC57AagPl2jY9mxCL/WqNabQ==2021-11-11T07:28:41Z
hash string : o6dD1qJbdrQvU86JUxZiKf8WBo0BH6oc+kN8CVNk2rM=

Using the data prepared so far, create the license token as follows.

// Add the following code after step 3 code
let tokenData = {
"drm_type": licenseInfo.drmType,
"site_id": siteInfo.siteId,
"user_id": licenseInfo.userId,
"cid": licenseInfo.contentId,
"policy": encryptedPolicy,
"timestamp": UTCTime,
"hash": hashString,
"response_format": "original",
"key_rotation": false
};
console.log("token json : " + JSON.stringify(tokenData));
let base64Token = Buffer.from(JSON.stringify(tokenData)).toString("base64");
console.log("base64 encoded token : " + base64Token);

First, JSON data is created by combining various input values and encrypted license rules, timestamps, and hash values according to the token specification. Converting the corresponding JSON data to a Base64 string completes the token for the client to use for DRM license requests.

The result of executing the 4th step code is as follows.

Terminal window
token json : `{"drm_type":"Widevine","site_id":"TUTO","user_id":"test-user","cid":"bigbuckbunny","policy":"sX7DEMZ1S2xaMoIt76m+yDwylZRVJ2Gzs2I1b0+mzL0X9FcJ43aAloqI5noG2iyC57AagPl2jY9mxCL/WqNabQ==","timestamp":"2021-11-11T07:28:41Z","hash":"o6dD1qJbdrQvU86JUxZiKf8WBo0BH6oc+kN8CVNk2rM=","response_format":"original","key_rotation":false}`
base64 encoded token : eyJkcm1fdHlwZSI6IldpZGV2aW5lIiwic2l0ZV9pZCI6IlRVVE8iLCJ1c2VyX2lkIjoidGVzdC11c2VyIiwiY2lkIjoiYmlnYnVja2J1bm55IiwicG9saWN5Ijoic1g3REVNWjFTMnhhTW9JdDc2bSt5RHd5bFpSVkoyR3pzMkkxYjArbXpMMFg5RmNKNDNhQWxvcUk1bm9HMml5QzU3QWFnUGwyalk5bXhDTC9XcU5hYlE9PSIsInRpbWVzdGFtcCI6IjIwMjEtMTEtMTFUMDc6Mjg6NDFaIiwiaGFzaCI6Im82ZEQxcUpiZHJRdlU4NkpVeFppS2Y4V0JvMEJINm9jK2tOOENWTmsyck09IiwicmVzcG9uc2VfZm9ybWF0Ijoib3JpZ2luYWwiLCJrZXlfcm90YXRpb24iOmZhbHNlfQ==

This completes the license token tutorial.