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 above example claims as JWT token and adding signature you will get the 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 DRM → Configuration → License Acquisition → Signing Key.
Such 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 field | Description | Example values |
---|---|---|
exp | The 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. Token has to be in GMT Unix Time stamp. | 1607351408 |
kid | An array of Key IDs for which this token will allow a license. KeyID here identifies the specific key used to ecrypt the stream. If “*” value is used, the token will allow a license for any stream. | ["fda991e1-3ed7-47a4-80b5-7c563c4a713e"], ["*"] |
cid | Can be used instead of "kid" parameter to bind the token to specific contentId. The contentId (cid) must be sent to Cloud DRM's KMS API (SPEKE2 or CPIX endpoint) as "contentId" attribute of root CPIX element. For AWS Media Package VOD this value is set at encryption tab (resource_id). | "1d1bd89d-3822-4255-a4da-ff57f63991d0" |
duration | common license duration for all DRM systems expressed in seconds. This is general timespan for consuming the license and playing the content. To use specific duration specification for selected DRM system, see below | 86400 |
ip | A player IP address for which this token will allow a license. If IP is not provided, the token will allow license for any IP. | "1.2.3.4" |
userid | A 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" |
nonce | Optional, random, unique identifier given for this 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 the nonce is not provided, the token will be valid for any number of requests up to its expiration time. | "ea5b56ac-adf6-11ed-afa1-0242ac120002" |
tlimit | specifies 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, the default 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. | 24 |
persistent | A boolean value indicating if the license can be persistent. Persistent license can be stored on the device and be reused to more that one video sessions. If you want to set persistency flag for specific DRM system, see below | true, false |
Widevine related
JSON field | Description | Example values |
---|---|---|
widevine | Object containing specific license parameters for Widevine | |
widevine.level | Widevine security level | 1,2,3 |
widevine.license_duration | License duration seconds for Widevine. Specifies the time window for this particular license. A value of 0 indicates unlimited duration time. | 86400 |
widevine.rental_duration | Rental duration seconds for Widevine. Specifies the time window when playback is permitted. A value of 0 indicates unlimited rental time. | 86400 |
widevine.playback_duration | Playback 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.hdcp | HDCP policy for Widevine: “HDCP_NONE”, “HDCP_V1”, “HDCP_V2”, “HDCP_V2_1”, “HDCP_V2_2”, “HDCP_NO_DIGITAL_OUTPUT” | “HDCP_V1” |
widevine.cgms | CGMS Analog protection for Widevine: “CGMS_NONE”; “COPY_FREE”; “COPY_ONCE”; “COPY_NEVER” | “COPY_NEVER” |
widevine.persistent | Persistency flag for widevine | true, false |
widevine.srm_rule | SRM rule for HDCP keys status | "DCP_SRM_RULE_NONE","CURRENT_SRM" |
widevine.disable_analog | forbids sending video to analog outputs | true, false |
widevine.soft_enforce_playback | Set to true to allow playback to continue even if license expires while viewing. | true,false |
widevine.soft_enforce_rental | Set to false to not allow playback to start beyond the rental window. | true,false |
widevine.timeshift_limit | Indicates 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_renew | ndicates that renewal of this license is allowed. If true, the duration of the license can be extended by heartbeat. | true,false |
widevine.renewal_recovery_duration | The 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_delay | How 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_interval | Specifies 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_usage | Indicates that the license shall be sent for renewal when usage is started. This field is only used if can_renew is true. | true, false |
Playready related
JSON field | Description | Example values |
---|---|---|
playready | Object containing specific license parameters for PlayReady | |
playready.persistent | persistency flag for PlayReady. Read more about PlayReady persistent licenses | true, false |
playready.level | Minimum security level for playready: 2000 or 3000. Read more about PlayReady security levels | 2000 |
playready.begin_date | The time where 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_date | The expiration time of persistent license validity for PlayReady | "2019-12-07T11:59:47.172533+01:00" |
playready.analog_video_opl | Output protection level for analog video content. Allowed values: 100, 150, 200. PlayReady output protection levels explanation | 200 |
playready.compressed_digital_audio_opl | Output protection level for compressed digital audio. Allowed values: 100, 150, 200, 250, 300. PlayReady output protection levels explanation | 300 |
playready.compressed_digital_video_opl | Output protection level for compressed digital video. Allowed values: 400, 500. PlayReady output protection levels explanation | 400 |
playready.uncompressed_digital_audio_opl | Output protection level for uncompressed digital audio. Allowed values: 100, 150, 200, 250, 300. PlayReady output protection levels explanation | 100 |
playready.uncompressed_digital_video_opl | Output protection level for uncompressed digital video. Allowed values:100, 250, 270, 300. PlayReady output protection levels explanation | 270 |
playready.first_play_expiration | First play expiration seconds. If set the license will expire after specified number of seconds after first content playback. | 3600 |
playready.grace_period | Grace periond seconds. Number of seconds during which the protected content can be played on client machine after its clock becomes unset. | 7200 |
playready.play_enablers | List of Play enablers (GUIDS) | ["786627D8-C2A6-44BE-8F88-08AE255B01A7"] |
Fairplay related
JSON field | Description | Example values |
---|---|---|
fairplay | Object containing specific license parameters for Fairplay | |
fairplay.persistent | persistency flag for fairplay | 7200 |
fairplay.rental_duration | Rental 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 the 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_duration | Key lease period. The client stops the playback when the lease expires. | 86400 |
fairplay.offline_storage_duration | The 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_duration | The asset playback validity duration in seconds. It is measured from the moment of the asset's first playback start. A value of zero indicates ulimited validity time. | 0 |
fairplay.hdcp | Put HDCP Enforecement tag into key response | true |
fairplay.hdcp_type | Apple HDCP Enforcement type. 0 or 1 | 1 |
Token generation example
In this section we will generate example JWT for obtaining DRM licenses from DRM Cloud service. First login to your DRM dashboard at https://console.videokit.cloud Go to DRM -> Configuration -> License acquisition and copy Signing Key. This Signing key should be use to create JWT tokens on your backend.
To generate a signed JWT token, 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 if you want to restrict content access with 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 (rential_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:
- Licence Duration = 180 mins
- Playback Duration = 600 mins
- 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.