Skip to main content

Token

UserToken at DRM license request

The UserToken is a mechanism that authorizes your application to allow the player to obtain a DRM license. By generating the UserToken on your backend and passing it to the player, you grant specific users the right to access DRM-protected content.

The Cloud DRM service requires the UserToken to follow standardized JWT syntax with an HS256 signature. This signature must be generated on your backend using a shared secret key, ensuring the authenticity of the token.

The UserToken is a JWT containing the expiration claim (exp) along with additional claims specific to the Cloud DRM service. Below is an example of the simplest JWT, which allows access to all DRM-protected content for 24 hours, valid until 2023-06-14:

{
"exp": 1686744249,
"kid": ["*"],
"duration": 86400
}

After encoding the example claims above as a JWT token and adding the signature, you will get a token like this:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE5MTc0OTgyNzgsImtpZCI6WyIqIl0sImR1cmF0aW9uIjo4NjQwMH0._zRj1xAdpNhQ0JEgCryvZ-4UkwHvQgwJjOkDBwQuK_A

The token can include additional parameters to further restrict the usage of the DRM license. For instance, you can enforce hardware decryption for enhanced security or require HDCP protection for digital video outputs. These parameters are optional—if they are not included in the token, the default settings defined in your DRM service configuration will be applied.

The token must be signed using the HmacSha256 algorithm, with the secret key Base64-encoded for activation. You can locate this secret key in the web console by navigating to DRMConfigurationLicense AcquisitionSigning Key.

This token should be passed in a license acquisition request as a UserToken querystring parameter or a X-Drm-UserToken HTTP Custom Header.

Parameters

Common

JSON fieldDescriptionExample values
expThe expiration date of this token is expressed as unix time. This field is a standard JWT claim. Typically, the token should be immediately returned to the player after creation. The player will use the token to acquire a license at the start of a playback. That means this value should be set to a short time after the start of a playback, for example: NOW()+10minutes. The token must use a GMT Unix timestamp.1607351408
kidAn array of Key IDs for which this token will allow a license. KeyID here identifies the specific key used to encrypt the stream. If the “*” value is used, the token will allow a license for any stream.["fda991e1-3ed7-47a4-80b5-7c563c4a713e"], ["*"]
cidCan be used instead of kid parameter to bind the token to specific contentId. The contentId (cid) must be sent to Cloud DRM's Key Management System (KMS) API (SPEKE2 or CPIX endpoint) as the contentId attribute of the root CPIX element. For AWS MediaPackage VOD, this value is set in the Encryption tab (resource_id)."1d1bd89d-3822-4255-a4da-ff57f63991d0"
durationCommon license duration for all DRM systems, expressed in seconds. This value represents the general timespan for consuming the license and playing the content. To use a specific duration specification for a selected DRM system, see the information below.86400
ipA player IP address for which this token will allow a license. If no IP is provided, the token will allow a license for any IP address."1.2.3.4"
useridA custom string that identifies the token on the video backend side. This string can include the actual user ID, player ID, or any other value that can be used for filtering requests in the request log."user1"
nonceOptional, random, unique identifier given for the token. If this field is put in the token, the token will be valid only once (for one license request, expiration time still applies). It is recommended to use this field for better security. If nonce is not provided, the token will be valid for any number of requests until its expiration time."ea5b56ac-adf6-11ed-afa1-0242ac120002"
tlimitSpecifies the usage limit for the token in terms of license requests, represented as an integer.- If tlimit is set, the nonce field must contain a random GUID or unique string.
- If only the nonce is provided without tlimit, the default value is tlimit = 1.
This parameter is useful for multi-key scenarios;
- For instance, if the content is encrypted with three keys, setting tlimit = 3 allows for three license requests.
- In live stream key rotation, setting tlimit = 24 enables 24 license requests, allowing playback for up to 24 hours if the key is rotated hourly.
persistentA boolean value indicating if the license can be persistent. Persistent license can be stored on the device and reused for more than one video session. If you want to set a persistency flag for a specific DRM system, see the information below.true, false
JSON fieldDescriptionExample values
widevineObject containing specific license parameters for Widevine.
widevine.levelWidevine security level expressed as EME enumeration (numbers 1 to 5, see below). Recommended values: 1 for L3, 5 for L11,5
widevine.license_durationLicense duration seconds for Widevine. Specifies the time window for this particular license. A value of 0 indicates unlimited duration time.86400
widevine.rental_durationRental duration seconds for Widevine. Specifies the time window when playback is permitted. A value of 0 indicates unlimited rental time.86400
widevine.playback_durationPlayback duration seconds for Widevine. Specifies the viewing time window from the start of a playback within the license duration. A value of 0 indicates unlimited duration time.7200
widevine.hdcpHDCP policy for Widevine: “HDCP_NONE”, “HDCP_V1”, “HDCP_V2”, “HDCP_V2_1”, “HDCP_V2_2”, “HDCP_NO_DIGITAL_OUTPUT”.“HDCP_V1”
widevine.cgmsCGMS Analog protection for Widevine: “CGMS_NONE”; “COPY_FREE”; “COPY_ONCE”; “COPY_NEVER”.“COPY_NEVER”
widevine.persistentPersistency flag for widevine.true, false
widevine.srm_ruleSRM rule for HDCP keys status."DCP_SRM_RULE_NONE","CURRENT_SRM"
widevine.disable_analogForbids sending video to analog outputs.true, false
widevine.soft_enforce_playbackSet to true to allow playback to continue even if license expires while viewing.true,false
widevine.soft_enforce_rentalSet to false to not allow playback to start beyond the rental window.true,false
widevine.timeshift_limitIndicates the allowed delay between the time the content was transmitted and the time the content is viewed. Essentially, this parameter indicates a future license start time. A value of 0 indicates start immediately. When a license is issued, it can be consumed immediately.180
widevine.can_renewIndicates that renewal of this license is allowed. If true, the duration of the license can be extended by heartbeat.true,false
widevine.renewal_recovery_durationThe window of time, in which playback is allowed to continue while renewal is attempted, yet unsuccessful due to backend problems with the license server. A value of 0 indicates unlimited. This field is only used if can_renew is true.3600
widevine.renewal_delayHow many seconds after license_start_time, before renewal is first attempted. This field is only used if can_renew is true.3600
widevine.renewal_retry_intervalSpecifies the delay in seconds between subsequent license renewal requests, in case of failure. This field is only used if can_renew is true.3600
widevine.renew_with_usageIndicates that the license shall be sent for renewal when usage is started. This field is only used if can_renew is true.true, false
widevine.allowed_device_typesList of allowed device types.["Phone", "TV"]
widevine.blocked_device_typesList of blocked device types.["Phone", "TV"]
widevine.allowed_device_vulnerability_levelsList of allowed vulnerability levels.[1,2,3]
widevine.blocked_device_vulnerability_levelsList of blocked vulnerability levels.[1,2]
widevine.allowed_resource_rating_tiersList of allowed rating tiers.[1,2]
widevine.blocked_resource_rating_tiersList of blocked rating tiers.[1,4]
widevine.min_oemcrypto_versionMinimal allowed EOM Crypto Version.2
widevine.allowed_platform_verification_statusesList of allowed platform verification statutes.["PLATFORM_SOFTWARE_VERIFIED","PLATFORM_HARDWARE_VERIFIED"]
widevine.blocked_platform_verification_statusesList of blocked platform verification statutes.

Widevine security levels

When specifying Widevine security level in the token, the EME number value should be used:

Widevine security levelCorresponding EME level number (used in token)EME Widevine robustness level
L31SW_SECURE_CRYPTO
L32SW_SECURE_DECODE
L23HW_SECURE_CRYPTO
L14HW_SECURE_DECODE
L15HW_SECURE_ALL

In most common scenarios, one of two Widevine security levels is used:

  • L3 ("level":1 in token) This security level relies on the secure bootloader to verify the system image. An AES crypto block performs the AES decryption of the media stream and the resulting clear media buffers are returned to the CPU for delivery to the video decoder.
  • L1 ("level":5 in token) Widevine DRM keys and decrypted content are never exposed to the host CPU. Only security hardware or a protected security co-processor uses clear key values and the media content is decrypted by the secure hardware.
JSON fieldDescriptionExample values
playreadyObject containing specific license parameters for PlayReady.-
playready.persistentPersistency flag for PlayReady. Read more about PlayReady persistent licenses.true, false
playready.levelMinimum security level for PlayReady: 2000 or 3000. Read more about PlayReady security levels.2000
playready.begin_dateThe time when the persistent license validity for PlayReady begins. Typically, you should use the current time. Format it as an ISO date."2019-12-06T11:59:47.172533+01:00"
playready.expiration_dateThe expiration time of persistent license validity for PlayReady."2019-12-07T11:59:47.172533+01:00"
playready.analog_video_oplOutput protection level for analog video content. Allowed values: 100, 150, 200. PlayReady output protection levels explanation.200
playready.compressed_digital_audio_oplOutput protection level for compressed digital audio. Allowed values: 100, 150, 200, 250, 300. PlayReady output protection levels explanation.300
playready.compressed_digital_video_oplOutput protection level for compressed digital video. Allowed values: 400, 500. PlayReady output protection levels explanation.400
playready.uncompressed_digital_audio_oplOutput protection level for uncompressed digital audio. Allowed values: 100, 150, 200, 250, 300. PlayReady output protection levels explanation.100
playready.uncompressed_digital_video_oplOutput protection level for uncompressed digital video. Allowed values: 100, 250, 270, 300. PlayReady output protection levels explanation.270
playready.first_play_expirationFirst play expiration seconds. If set, the license will expire after a specified number of seconds after the first content playback.3600
playready.grace_periodGrace period in seconds. The number of seconds during which the protected content can be played on the client machine after its clock becomes unset.7200
playready.play_enablersList of Play enablers (GUIDS).["786627D8-C2A6-44BE-8F88-08AE255B01A7"]
JSON fieldDescriptionExample values
fairplayObject containing specific license parameters for FairPlay.
fairplay.persistentPersistency flag for FairPlay.7200
fairplay.rental_durationRental duration seconds for FairPlay. FPS does not start the decryption if the content key has expired. However, FPS continues the user experience if the content key expires during playback. If a playback is attempted again with an expired key, the client will decline it. For offline playback, this value represents the offline key persistency expiration.86400
fairplay.lease_durationKey lease period. The client stops the playback when the lease expires.86400
fairplay.offline_storage_durationThe asset storage validity duration in seconds. It is measured from the moment of the license acquisition. A value of zero indicates unlimited validity time.86400
fairplay.offline_playback_durationThe asset playback validity duration in seconds. It is measured from the moment of the asset's first playback start. A value of zero indicates unlimited validity time.0
fairplay.hdcpPut the HDCP Enforcement tag into the key response.true
fairplay.hdcp_typeApple HDCP Enforcement type. 0 or 1."AppleMain"
fairplay.required_security_levelRequired Security Level for the device. If specified, the license server will only deliver content to devices that meet or exceed this security level requirement. Allowed values: "Audio", "AppleBaseline", "AppleMain"1

Token generation example

In this section, we will generate an example JWT for obtaining DRM licenses from the DRM Cloud service. First, login to your DRM dashboard at https://console.videokit.cloud Go to DRMConfigurationLicense acquisition and copy the Signing Key. This signing key should be used to create JWT tokens on your backend.

To generate a signed JWT, you can use the following Python script with the PyJWT package. In the example below, only the required token claims are included. For testing purposes, the token's validity is set until the year 2025. However, in a typical scenario, the token should be generated by the backend just before playback begins, and the "exp" (expiration) field should be set to NOW() + 10 minutes.

import jwt
import json
import base64

base64_signingkey = 'put signing key here'

payload = {
"exp": 1735689600, #put future timestamp here
"kid": ["*"],
"duration": 86400
}

binary_signingkey = base64.b64decode(base64_signingkey)
encoded_jwt = jwt.encode(payload, binary_signingkey, algorithm='HS256')
print(encoded_jwt)

The token will look like this:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE5MTc0OTgyNzgsImtpZCI6WyIqIl0sImR1cmF0aW9uIjo4NjQwMH0._zRj1xAdpNhQ0JEgCryvZ-4UkwHvQgwJjOkDBwQuK_A

If you need to specify extended parameters of the license, you can use the more detailed token payload example:

import jwt
import json
import base64

base64_signingkey = 'put signing key here'

payload = {
"exp": 1917498278,
"kid": ["*"],
"duration": 86400,
"widevine": {
"level": 1,
"hdcp": "HDCP_V2",
"license_duration": 3600
},
"playready": {
"level" : 3000,
"uncompressed_digital_video_opl" : 300,
},
"fairplay": {
"hdcp":true
}
}

binary_signingkey = base64.b64decode(base64_signingkey)
encoded_jwt = jwt.encode(payload, binary_signingkey, algorithm='HS256')
print(encoded_jwt)

The resulting token will look like this:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE5MTc0OTgyNzgsImtpZCI6WyIqIl0sImR1cmF0aW9uIjo4NjQwMCwid2lkZXZpbmUiOnsibGV2ZWwiOjEsImhkY3AiOiJIRENQX1YyIiwibGljZW5zZV9kdXJhdGlvbiI6MzYwMH0sInBsYXlyZWFkeSI6eyJsZXZlbCI6MzAwMCwidW5jb21wcmVzc2VkX2RpZ2l0YWxfdmlkZW9fb3BsIjozMDB9LCJmYWlycGxheSI6eyJoZGNwIjp0cnVlfX0.-YK8vULyooj6K3Fee4hffOl9uhZSq2y_4K9H5ac2Fjs

Offline DRM license

To allow offline playback, DRM licenses can be saved locally. To enable this feature, set the persistent parameter to true. Additionally, there are a few parameters that need to be configured specifically for Widevine and Fairplay offline playback scenarios.

Widevine

Duration periods

  • License_Duration (license_duration_seconds) - Specifies the total time the content is available for playback.
    • This is a fixed value. Once the duration expires (counts down to 0), no further decryption of the content is allowed.
    • This parameter is required to restrict content access via a license.
  • Playback Duration (playback_duration_seconds) – Defines how long the license remains valid after playback starts for the first time.
    • This parameter is typically used in offline playback or renewal scenarios.
    • If this parameter is unspecified, the license remains valid indefinitely after the first playback.
  • Rental_Duration (rental_duration_seconds) - Determines the time period the license is valid before the first playback starts.
    • Once the content has been played, this parameter is no longer applied or enforced.
    • This parameter is primarily used in offline playback scenarios.
    • If this parameter is unspecified, the license is valid indefinitely until the first playback.

Examples:

  • License Duration = 180 min
  • Playback Duration = 600 min
  • Rental Duration = 30 days

FairPlay

FairPlay offline key storage

Starting with iOS 11.0, FairPlay Streaming (FPS) introduces a new feature for enabling offline rentals. This feature allows the server to specify two expiration times for the content, creating a "dual expiry" mechanism similar to how iTunes movie rentals work. The two properties that can be specified are:

  • Storage Duration (seconds) – Defines the maximum time the license (key) remains valid before playback starts. This duration is measured from the time the license is acquired.

  • Playback Duration (seconds) – Specifies the maximum time the license remains valid after playback has started. This duration is measured from the first time the content is played.

Tokens for Multikey scenario

Motivation

In the multikey scenario, the stream is encrypted with multiple keys. Each track (for example, video quality) is encrypted using a separate key and requires a separate DRM license. This makes it possible to issue licenses with different protection settings for different tracks. Typically, HD and 4K tracks require a higher level of protection, including Widevine L1 and PlayReady SL3000.

Prerequisites

In order to use the multikey functionality of Cloud DRM the packager, when requesting the keys from KMS API, you must send intendedTrackType attribute of ContentKeyUsageRule element of CPIX document. Only then can the Cloud DRM license endpoint recognize the track type that the license is requested for. The intendedTrackType attribute can be set to any string value, but recommended track names are: AUDIO, VIDEO, SD, HD, UHD.

Multikey token policies

For the multikey stream, the player requests multiple licenses from the license endpoint, typically using the same JWT token. In order to vary protection settings per track, the token must contain a "tracks" section documented below.

JSON fieldDescriptionExample values
tracksList of separate per-track objects, each containing parameters that will override top level token parameters for a given track
tracks[].typesList of track types that this object will apply to["HD","4K"]
tracks[].widevineObject containing Widevine parameters for given track(s){"level":5}
tracks[].playreadyObject containing Playready parameters for given track(s){"level":3000}
tracks[].fairplayObject containing Fairplay parameters for given track(s){"hdcp":true}

Example token payload enforcing different protection parameters for AUDIO and for HD, 4K

{
"exp": 1735689600, //put future timestamp here
"kid": ["*"],


//top level statements - applied to all tracks
"duration": 86400,
"widevine" : { "level": 1 },
"playready" : { "level": 2000 }

//per track type statements - override defaults
"tracks" : [
{
"types" : ["AUDIO"],
"fairplay" : { "required_security_level" : "Audio" }
},
{
"types" : ["HD", "4K"],
"widevine" : { "level": 5 },
"playready" : { "level": 3000 }
"fairplay" : { "required_security_level" : "AppleMain" }
},
]
}

For the above token:

  • If the track type is not known, or different that HD, 4K: Widevine L3 / Playready SL2000 license is produced.
  • For AUDIO track for fairplay: required_security_level flag is set to Audio - such a license can be only used for Audio.
  • For 4K or HD tracks Widevine L1 / Playready SL3000 license is produced. Effectively, this blocks HD and 4K qualities for devices that cannot fulfill these protection settings.