License Token Guide

Overview

There are two types of methods for issuing multi-DRM (FPS, Widevine, PlayReady, NCG) licenses from PallyCon cloud server.

  1. Callback type

    • When PallyCon cloud server receives license request from multi-DRM client, it first checks service site’s callback page to see if the user has valid permissions.
    • In the case of a request from an authorized user, the service site returns information such as authentication, usage rights (unlimited, fixed period) and various security options to the PallyCon cloud server through the callback web page.
    • PallyCon cloud server receives the response from the callback page and issues the license to the client.
  2. Token type

    • When a multi-DRM client tries to play DRM content, the client requests a token to the service site in order to acquire DRM license. The service site verifies that the user requesting the token has permission to the content, and then generates a token data according to the specification.
    • The service site can set usage rights (expiration date or unlimited) and various security options inside of the token data. The generated token is delivered to the client as response.
    • When a client requests a license with a token, the PallyCon cloud server validates the token and issues a license.

This document describes the second method, the specification of license token. Please refer to License Callback Guide if you want callback type integration.

Token License Issuance Workflow

sequenceDiagram participant A as End user (Client) participant B as Content Service Site participant C as PallyCon Cloud Server A ->> B: Login to service site B -->> B: Authenticate user B ->> A: Send available content list A -->> A: Select content to play opt License Token Integration A ->> B: Request token B -->> B: Authorize and create license token B ->> A: Send license token end A ->> C: Request DRM license with token C -->> C: Verify token C ->> A: Issue DRM license A -->> A: Playback content

(1) Request a token to service site

  • Client requests its service site for a token to playback DRM content.

(2) Token generation (see Specification below)

  • The service site checks the request received from the client and generates a token if the user has permission to use the content.
  • Token includes information such as Content ID, user ID, timestamp, and license rules.

(3) Token transfer

  • The service site returns the generated token to the client as a response. > The creation of the token and the request / response function are not provided by the PallyConnect SDK product. The service site should implement these functions according to this guide.

(4) Request for a license

(5) Issuing a license

  • PallyCon cloud server validates the token and issues a license according to the rules in the token.

Token Generation Specification

  • The service site generates the following JSON token for the request from the client and sends the base64 encoded string as the response.

  • You can test generating token by entering key values of the following specification in DevConsole page of PallyCon site.

Token JSON Format

{
    "drm_type": "<drm type string>",
    "site_id": "<site id string>",
    "user_id": "<user id string>",
    "cid": "<content id string>",
    "token": "<base64(aes256(token data for license generation))>",
    "timestamp": "<token validity start time (GMT) as yyyy-mm-ddThh:mm:ssZ>",
    "hash": "<base64(sha256(hash message format))>"
}
Name Value Required Description
drm_type string No Type of DRM (“NCG”, “Widevine”, “PlayReady”, “FairPlay”), Default : “PlayReady”
site_id string Yes Service Site ID which is issued by PallyCon Console
user_id string Yes End-user’s ID which is managed by the service site. Input “LICENSETOKEN” if there is no user ID.
cid string Yes Unique ID of the content. The CID is used in DRM content packaging as well.
token base64 encoded string Yes Token Data in JSON (refer to specification) which is encrypted by AES256 and encoded as Base64 string.
timestamp string Yes Token validity start time (usually current time) as ‘yyyy-mm-ddThh:mm:ssZ’(GMT). Token is valid for 600 seconds after the timestamp. (can be adjusted on Console site)
hash base64 encoded string Yes Hash message (refer to specification) which is hashed by SHA256 and encoded as Base64 string.

Token JSON example

{
    "drm_type":"Widevine",
    "site_id":"ABCD",
    "user_id":"LICENSETOKEN",
    "cid":"sample-content-id-0123",
    "token":"uZ0ALHJDHdZKc9pICii6Hog46frSIl+to/Wbf08uqliQVjGwK0Lw40onRM743ttDledSqjD1RfgdZUqq/X44/ZMQvHob5aOsINRmQ0bx6oJofuS5RRDRKEOVdt8bW09ReOAY5skHcBNnAOzkiDW6ICGlGrFqS12v7xJKrhutYmU4uB1bgLW7pdAwX87RXJ7NBogFvWohCpcnMxgD8EV0CswNEvkmX/27iXYGmniMd2DG+iEe2CismUbpWbl6sHkLh9gw1n4OTXSfU70A0VUSUVbwWW1UXYJxutaowJvxsYKfPGsmyAGLjfsBsAJYfOiFJcVW2SbVld6E7YETTAtL/QqUwUxXGxwQ+8an3e50AbM6HXsi8h00gjiiWHTg0PUJYKJ8SA2jZcPuA+ItiEmsN+QFWuu4aJCnw6Qek3QojLhwLhY7gK3seruFg5BvJnadjkCXdzFzlT6VHiisTHa67BVMownCwx3Zh5lGIq+z2wJBcjNv8Q3QGlJSE1NJTVb4RsX9lywX63FepHVUaWcxEcr2paT1tVZA2tuOzKyUNjL8HZeWpaHMHq938r56qPu6JcdYKptzQTTvL4g4AmMt2pW9xAEAivNdZGh+4vm6foDP+cW55FpI7zNubHoYC/yxrJOg2SfCbmW3adxVeZydiVM+ujndXybx49qoWykEVhkJwj1AmDA7VEJvxI3e6kgvce95NEwuq8N1FdN1tizplOIUxlK4tey4AuHSnu48ufGr0OlUTL+o6wEjivU6n3asxvD/5bGla2CxnnnCKaGbeaucMKK7BDRq9F1SzDqRYogVBjSc5wv6105qJ7OetSEb2aP09bYGRwrO3r2/ZBValVfDqR1V9ciEOX8e6rNPFZ/YJF45PjseeC9xR1Q+4GEgSL7EUAxZkPv/+EOgnh1ACg4VxXxi4rPZ5S1Zm8PcEXpUG1JKvptI9QPLHsuooTSH19J9KPFzmjm9BgYAsPQFQy804nozWaBBkh58jaU1lJU=",
    "timestamp":"2018-04-14T23:59:59Z",
    "hash":"QkM4NDVGMDMxRUE4MDM0NUMzQUE4MTgyMTA4QTQ2QjQyNEFBNTJCNkQ1QjhGODg1NUE1MDI2NjQ2NkE2QUNBNA=="
}

Note:

The token and hash strings shown in the above example are not valid data. They are for reference only. For practical application, use the values generated according to this specification.

Example of Token String

  • The below string is the result of Base64 encoding for the above JSON example.
ewogICAg4oCcZHJtX3R5cGXigJ064oCdV2lkZXZpbmXigJ0sCiAgICDigJxzaXRlX2lk4oCdOuKAnUFCQ0TigJ0sCiAgICDigJx1c2VyX2lk4oCdOuKAnUxJQ0VOU0VUT0tFTuKAnSwKICAgIOKAnGNpZOKAnTrigJ1zYW1wbGUtY2VudGVudC1pZC0wMTIz4oCdLArigJx0b2tlbuKAnTrigJ11WjBBTEhKREhkWktjOXBJQ2lpNkhvZzQ2ZnJTSWwrdG8vV2JmMDh1cWxpUVZqR3dLMEx3NDBvblJNNzQzdHREbGVkU3FqRDFSZmdkWlVxcS9YNDQvWk1RdkhvYjVhT3NJTlJtUTBieDZvSm9mdVM1UlJEUktFT1ZkdDhiVzA5UmVPQVk1c2tIY0JObkFPemtpRFc2SUNHbEdyRnFTMTJ2N3hKS3JodXRZbVU0dUIxYmdMVzdwZEF3WDg3UlhKN05Cb2dGdldvaENwY25NeGdEOEVWMENzd05FdmttWC8yN2lYWUdtbmlNZDJERytpRWUyQ2lzbVVicFdibDZzSGtMaDlndzFuNE9UWFNmVTcwQTBWVVNVVmJ3V1cxVVhZSnh1dGFvd0p2eHNZS2ZQR3NteUFHTGpmc0JzQUpZZk9pRkpjVlcyU2JWbGQ2RTdZRVRUQXRML1FxVXdVeFhHeHdRKzhhbjNlNTBBYk02SFhzaThoMDBnamlpV0hUZzBQVUpZS0o4U0EyalpjUHVBK0l0aUVtc04rUUZXdXU0YUpDbnc2UWVrM1Fvakxod0xoWTdnSzNzZXJ1Rmc1QnZKbmFkamtDWGR6RnpsVDZWSGlpc1RIYTY3QlZNb3duQ3d4M1poNWxHSXErejJ3SkJjak52OFEzUUdsSlNFMU5KVFZiNFJzWDlseXdYNjNGZXBIVlVhV2N4RWNyMnBhVDF0VlpBMnR1T3pLeVVOakw4SFplV3BhSE1IcTkzOHI1NnFQdTZKY2RZS3B0elFUVHZMNGc0QW1NdDJwVzl4QUVBaXZOZFpHaCs0dm02Zm9EUCtjVzU1RnBJN3pOdWJIb1lDL3l4ckpPZzJTZkNibVczYWR4VmVaeWRpVk0rdWpuZFh5Yng0OXFvV3lrRVZoa0p3ajFBbURBN1ZFSnZ4STNlNmtndmNlOTVORXd1cThOMUZkTjF0aXpwbE9JVXhsSzR0ZXk0QXVIU251NDh1ZkdyME9sVVRMK282d0VqaXZVNm4zYXN4dkQvNWJHbGEyQ3hubm5DS2FHYmVhdWNNS0s3QkRScTlGMVN6RHFSWW9nVkJqU2M1d3Y2MTA1cUo3T2V0U0ViMmFQMDliWUdSd3JPM3IyL1pCVmFsVmZEcVIxVjljaUVPWDhlNnJOUEZaL1lKRjQ1UGpzZWVDOXhSMVErNEdFZ1NMN0VVQXhaa1B2LytFT2duaDFBQ2c0VnhYeGk0clBaNVMxWm04UGNFWHBVRzFKS3ZwdEk5UVBMSHN1b29UU0gxOUo5S1BGem1qbTlCZ1lBc1BRRlF5ODA0bm96V2FCQmtoNThqYVUxbEpVPSDigJwKICAgIOKAnHRpbWVzdGFtcOKAnTrigJ0yMDE4LTA0LTE0VDIzOjU5OjU5WuKAnSwK4oCcaGFzaOKAnTrigJ1Ra000TkRWR01ETXhSVUU0TURNME5VTXpRVUU0TVRneU1UQTRRVFEyUWpReU5FRkJOVEpDTmtRMVFqaEdPRGcxTlVFMU1ESTJOalEyTmtFMlFVTkJOQT094oCdCn0K

Token Data JSON Format

  • Encrypt the JSON value configured in the following format with AES256, and use the Base64 encoded string as the ‘token’ value of the Token JSON.
  • For AES256 encryption method, refer to specifications.
{
    "playback_policy": {
        "limit": <true|false>,
        "persistent": <true|false>,
        "duration" : <int(seconds)>,
        "expire_date": "<license expiry time (GMT) as yyyy-mm-ddThh:mm:ssZ>"
    },
    "security_policy": {
        "hardware_drm": <true|false>,
        "output_protect": {
            "allow_external_display" : <true|false>,
            "control_hdcp": <0|1|2>
        },
        "allow_mobile_abnormal_device" : <true|false>,
        "playready_security_level": <150|2000>
    },
    "external_key": {
        "mpeg_cenc": {
            "key_id" : "<hex-string>",
            "key" : "<hex-string>",
            "iv" : "<hex-string>"
        },
        "hls_aes" : {
            "key" : "<hex-string>",
            "iv" : "<hex-string>"
        },
        "ncg":{
            "cek":"<hex-string>"
        }
    }
}
Name Value Required Description
playback_policy json No license rules related with playback (refer to spec)
security_policy json No license rules related with security (refer to spec)
external_key json No Uses external content key to generate license. (refer to spec)

playback_policy

Name Value Required Description
limit boolean No whether playback period is limited (default: false)
true : limited playback period, false : unlimited
persistent boolean No whether the license is persistent. (default: false)
true : keep license, false : remove license after play(for streaming)
duration number Select duration of playback (unit: second). ‘expire_date’ is ignored if ‘duration’ is set.
‘limit’ should be true to apply this setting.
expire_date string Select date of license expiration, GMT Time 'yyyy-mm-ddThh:mm:ssZ' ‘limit’ should be true to apply this setting. This setting cannot be used with ‘duration’.

security_policy

Name Value Required Description
hardware_drm boolean No Whether hardware DRM is required.(default: false) valid for CENC (Widevine Modular) contents only
output_protect json No settings for external display (refer to spec)
allow_mobile_abnormal_device boolean No whether rooted device is allowed (default: false)
playready_security_level number No Security level of PlayReady DRM, 150,2000 (default: 150)

security_policy.output_protect

Name Value Required Description
allow_external_display boolean No Whether external display is allowed. (default: false) valid for NCG DRM only
control_hdcp number No Setting for applying HDCP. (default: 0)
0 : No HDCP, 1 : HDCP 1.4, 2 : HDCP 2.2

external_key

Name Value Required Description
mpeg_cenc json No CENC external key setting for PlayReady/Widevine (refer to spec)
hls_aes json No HLS AES external key setting for FairPlay Streaming (refer to spec)
ncg json No NCG DRM external key setting (refer to spec)

external_key.mpeg_cenc

Name Value Required Description
key_id hex-string No Key ID for DASH CENC packaging(PlayReady/Widevine). 16byte hex string
key hex-string No Key for DASH CENC packaging. 16byte hex string
iv hex-string No IV for DASH CENC packaging. 16byte hex string

external_key.hls_aes

Name Value Required Description
key hex-string No Key for HLS Sample AES packaging(FairPlay Streaming). 16byte hex string
iv hex-string No IV for HLS Sample AES packaging. 16byte hex string

external_key.ncg

Name Value Required Description
cek hex-string No CEK for NCG packaging. 32byte hex string

Token Data JSON Example

{
    "playback_policy":{
        "limit":true,
        "persistent":true,
        "duration":3600,
        "expire_date":"2018-04-20T23:59:59Z"
    },
    "security_policy":{
        "hardware_drm":true,
        "output_protect": {
            "allow_external_display":false,
            "control_hdcp":1
        },
        "allow_mobile_abnormal_device":false,
        "playready_security_level":150
    },
    "external_key": {
        "mpeg_cenc": {
            "key_id" : "30313233343536373839616263646566",
            "key" : "30313233343536373839616263646566",
            "iv" : "30313233343536373839616263646566"
        },
        "hls_aes" : {
            "key" : "30313233343536373839616263646566",
            "iv" : "30313233343536373839616263646566"
        },
        "ncg":{
            "cek":"3031323334353637383961626364656630313233343536373839616263646566"
        }
    }
}

SHA256 Hash Message Format

  • The hash message is used to verify the integrity of the entire token JSON value and should be generated as follows:
base64( sha256( <site access key> + <drm type> + <site id> + <user id> + <cid> + <token> + <timestamp> ) )
  1. Generate a string by concatenating the values of the access key of the service site and the values excluding the ‘hash’ field of the token JSON in order. Access key can be found on PallyCon Console site.
  2. Find the sha256 hash of the string created above.
  3. Encode the sha256 hash value using base64 to produce the final hash message string.

SHA256 Hash Message Example

Step 1. origin string
<Access Key>WidevineABCDLICENSETOKENsample-centent-id-0123uZ0ALHJDHdZKc9pICii6Hog46frSIl+to/Wbf08uqliQVjGwK0Lw40onRM743ttDledSqjD1RfgdZUqq/X44/ZMQvHob5aOsINRmQ0bx6oJofuS5RRDRKEOVdt8bW09ReOAY5skHcBNnAOzkiDW6ICGlGrFqS12v7xJKrhutYmU4uB1bgLW7pdAwX87RXJ7NBogFvWohCpcnMxgD8EV0CswNEvkmX/27iXYGmniMd2DG+iEe2CismUbpWbl6sHkLh9gw1n4OTXSfU70A0VUSUVbwWW1UXYJxutaowJvxsYKfPGsmyAGLjfsBsAJYfOiFJcVW2SbVld6E7YETTAtL/QqUwUxXGxwQ+8an3e50AbM6HXsi8h00gjiiWHTg0PUJYKJ8SA2jZcPuA+ItiEmsN+QFWuu4aJCnw6Qek3QojLhwLhY7gK3seruFg5BvJnadjkCXdzFzlT6VHiisTHa67BVMownCwx3Zh5lGIq+z2wJBcjNv8Q3QGlJSE1NJTVb4RsX9lywX63FepHVUaWcxEcr2paT1tVZA2tuOzKyUNjL8HZeWpaHMHq938r56qPu6JcdYKptzQTTvL4g4AmMt2pW9xAEAivNdZGh+4vm6foDP+cW55FpI7zNubHoYC/yxrJOg2SfCbmW3adxVeZydiVM+ujndXybx49qoWykEVhkJwj1AmDA7VEJvxI3e6kgvce95NEwuq8N1FdN1tizplOIUxlK4tey4AuHSnu48ufGr0OlUTL+o6wEjivU6n3asxvD/5bGla2CxnnnCKaGbeaucMKK7BDRq9F1SzDqRYogVBjSc5wv6105qJ7OetSEb2aP09bYGRwrO3r2/ZBValVfDqR1V9ciEOX8e6rNPFZ/YJF45PjseeC9xR1Q+4GEgSL7EUAxZkPv/+EOgnh1ACg4VxXxi4rPZ5S1Zm8PcEXpUG1JKvptI9QPLHsuooTSH19J9KPFzmjm9BgYAsPQFQy804nozWaBBkh58jaU1lJU=2018-04-14T23:59:59Z

Step 2. Hash value
BC845F031EA80345C3AA8182108A46B424AA52B6D5B8F8855A50266466A6ACA4

Step 3. base64 string (final result)
QkM4NDVGMDMxRUE4MDM0NUMzQUE4MTgyMTA4QTQ2QjQyNEFBNTJCNkQ1QjhGODg1NUE1MDI2NjQ2NkE2QUNBNA==

AES256 Encryption

  • AES256 Encryption/Decryption should be processed as below using site authentication key which is created by ‘Service Request’ on PallyCon Console site. ( The key can be found on PallyCon Console’s settings page )
  • You can test AES256 encryption / decryption from the DevConsole page on the PallyCon site.
AES256 Encryption
- mode : CBC
- key : 32 byte (Site key from PallyCon Console site)
- iv : 16 byte (0123456789abcdef)
- padding : pkcs7