Unified JWT Specifications
This document describes the detailed specifications of the Unified JWT(JSON Web Token) for secure playback and player feature control of standard content(unencrypted) and Kollus DRM content. Beyond simple playback authentication, you can define various security and convenience features directly on the customer server — such as playback speed restrictions, content exposure section settings, and watermarking — in accordance with your service policies.
JWT technical specifications
Encryption algorithm
Kollus VOD supports only the HMAC SHA-256(HS256) algorithm.
Header: { "alg": "HS256", "typ": "JWT" }
Authentication keys
The following two keys are used when generating and calling a JWT.
Security key
- Description: A secret key used for JWT signing and verification. Be careful not to expose it externally.
- Where to find: Kollus VOD console > [Service account] > [Custom key]
To change the security key, please contact Technical Support(tech_support@catenoid.net).
Custom key (custom_key)
- Description: An encrypted value of the security key, used together with the security key for authentication (JWT).
- Where to find: Kollus VOD console > [Service account] > [Custom key]
- The value may be updated upon browser refresh; copy and apply the latest value at the time of use.
Request URL format
https://v.kr.kollus.com/s?jwt={JWT}&custom_key={CUSTOM_KEY}
- Standard Claim usage restrictions: Errors may occur when using Claims defined in the RFC 7519 - Registered Claim Names specification.
- Enabling watermarking: The watermarking feature is disabled by default. To enable this feature, please contact the Account Manager(biz@catenoid.net) or Technical Support(tech_support@catenoid.net).
- iOS full-screen mode: When switching to full screen in an iOS environment, the iOS Native player is launched.
- Feature limitations: When playing in full screen on iOS or Samsung Internet Browser, Kollus player features such as watermark display may be restricted.
JWT Payload detailed specifications
Required options example
This is the basic Payload structure for a user (catenoid) to play a specific content item (vnCVPVyV).
{
"cuid": "catenoid",
"expt": 1703980800,
"mc": [
{
"mckey": "vnCVPVyV"
}
]
}
Basic options
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
cuid | string | ◯ | - | User ID
|
expt | integer | ◯ | - | JWT expiration date (Unix timestamp)
|
mc | array | ◯ | - | Array containing playback content information |
next_episode | boolean | - | false | Whether to trigger the next episode callback
|
playback_rates | array | - | - | List of playback speeds available to the user
|
playcallback_ignore | boolean | - | false | Whether to ignore playback callback transmission
|
Content options (settings inside the mc array)
For key (Key/ID) information, refer to the document below.
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
mckey | string | ◯ | - | Media content key |
mcpf | string | - | null | Encoding profile key
|
title | string | - | null | Content title
|
intr | boolean | - | false | Whether the content is an intro/outro video
|
seek | boolean | - | true | Whether seeking (scrubbing) is allowed
|
seekable_end | integer | - | -1 | End point of allowed seek range (sec)
|
disable_playrate | boolean | - | false | Disable playback speed selection
|
disable_nscreen | boolean | - | false | Disable resume playback feature
|
scroll_event | boolean | - | false | Whether to apply scroll events
|
bookmark | boolean | - | true | Whether to display the bookmark button |
Content exposure section settings
Kollus VOD does not provide physical editing of the original file (cutting, merging, etc.), but you can configure a specific section of registered content to be exposed to users.
- Feature definition: Specifies the start point (
start_time) and end point (end_time) within the original video that are available for playback and distributes accordingly. - Key characteristics
- No video editing: Physical data-level editing such as cutting or merging the original video file after upload is not supported.
- Distribute specific sections: Video outside the configured section is not loaded in the user's player; only the specified section is exposed to users.
- Flexible management: Without duplicating or re-uploading the original file, a single file can be used as multiple posts simply by changing the configuration values.
| Option | Type | Default | Description |
|---|---|---|---|
play_section.start_time | integer | null | Playback section start point (sec) |
play_section.end_time | integer | null | Playback section end point (sec) |
Subtitle settings
To expose only specific subtitles, set both the filter and show_by_filter options to true.
| Option | Type | Default | Description |
|---|---|---|---|
subtitle_policy.filter.name | string | null | Subtitle filter - subtitle name |
subtitle_policy.filter.language_code | string | null | Subtitle filter - language code |
subtitle_policy.filter_main.name | string | null | Main subtitle filter - subtitle name |
subtitle_policy.filter_main.language_code | string | null | Main subtitle filter - language code |
subtitle_policy.filter_sub.name | string | null | Sub subtitle filter - subtitle name |
subtitle_policy.filter_sub.language_code | string | null | Sub subtitle filter - language code |
subtitle_policy.show_by_filter | boolean | false | Whether to display subtitles based on filter criteria |
subtitle_policy.is_showable | boolean | false | Whether to display subtitles |
Watermarking
Overlays user identification information on the screen to prevent unauthorized recording and leakage.
- Enabling the feature: The watermarking feature is disabled by default. To enable this feature, please contact the Account Manager(biz@catenoid.net) or Technical Support(tech_support@catenoid.net).
- Tamper prevention: Protection against watermark tampering via external scripts (JavaScript Injection) is applied by default.
| Option | Type | Default | Description |
|---|---|---|---|
video_watermarking_code_policy.code_kind | string | - | Watermark display text
|
video_watermarking_code_policy.font_size | integer | 7 | Watermark text size (px) |
video_watermarking_code_policy.font_color | string | "FFFFFF" | Watermark color (hex) |
video_watermarking_code_policy.alpha | integer | 200 | Watermark opacity (0–255) |
video_watermarking_code_policy.show_time | integer | 1 | Watermark display duration (sec) |
video_watermarking_code_policy.hide_time | integer | 60 | Watermark hidden duration (sec) |
video_watermarking_code_policy.show_paused | boolean | false | Whether to display the watermark when paused |
video_watermarking_code_policy.enable_html5_player | boolean | false | Whether to use Kollus Web Player
|
PHP implementation example
<?php
/**
* base64_urlencode
*
* @param string $str
* @return string
*/
function base64_urlencode($str) {
return rtrim(strtr(base64_encode($str), '+/', '-_'), '=');
}
/**
* jwt_encode
*
* @param array $payload
* @param string $key
* @return string
*/
function jwt_encode($payload, $key) {
$jwtHead = base64_urlencode(json_encode(array('typ' => 'JWT', 'alg' => 'HS256')));
$jsonPayload = base64_urlencode(json_encode($payload));
$signature = base64_urlencode(hash_hmac('SHA256', $jwtHead . '.' . $jsonPayload, $key, true));
return $jwtHead . '.' . $jsonPayload . '.' . $signature;
}
$securityKey = 'SECURITY_KEY';
$customKey = 'CUSTOM_KEY';
$mediaContentKey = 'MEDIA_CONTENT_KEY';
$clientUserId = 'CLIENT_USER_ID';
$expireTime = 7200; // 120 minutes
$mediaItems = array(
array(
'media_content_key' => $mediaContentKey,
),
);
$payload = array(
'mc' => array(),
'cuid' => $clientUserId,
'expt' => time() + $expireTime,
'video_watermarking_code_policy' =>
array(
'code_kind' => '2930451',
'font_size' => 20,
'font_color' => 'ffffff',
'show_time' => 10,
'hide_time' => 1,
'alpha' => 255,
'enable_html5_player' => true
),
);
foreach ($mediaItems as $mediaItem) {
$mcClaim = array();
$mcClaim['mckey'] = $mediaItem['media_content_key'];
$payload['mc'][] = $mcClaim;
}
$jwtToken = jwt_encode($payload, $securityKey);
$webTokenURL = 'https://v.kr.kollus.com/s?jwt=' . $jwtToken . '&custom_key=' . $customKey;
?>
<!DOCTYPE html>
<html lang="en">
<body>
<iframe width="840" height="472" src="<?php echo $webTokenURL; ?>" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe>
</body>
</html>
Usage examples
Continuous playback of intro + main content + outro
An example configured to play the intro, main content, and outro as a single uninterrupted piece of content.
{
"cuid": "{END_USER_ID}",
"expt": 1735660800,
"mc": [
{
"mckey": "gDV2B1ZG",
"intr": true
},
{
"mckey": "vnCVPVyV"
},
{
"mckey": "eBzkZtzG",
"intr": true
}
]
}
Continuous playback of intro followed by main content
An example configured to disable seeking in the intro and automatically transition to the main content.
{
"cuid": "{END_USER_ID}",
"expt": 1735660800,
"mc": [
{
"mckey": "gDV2B1ZG",
"intr": true,
"seek": false
},
{
"mckey": "vnCVPVyV"
}
]
}
Allow seeking only within the 0–30 second range
An example that blocks full seeking but allows seeking within the first 30 seconds, useful as a preview clip.
{
"cuid": "{END_USER_ID}",
"expt": 1735660800,
"mc": [
{
"mckey": "gDV2B1ZG",
"intr": true,
"seekable_end": 30,
"seek": false
}
]
}
Allow seeking only within the watched section
An example that allows seeking only within the already-watched section and restricts arbitrary seeking into unwatched sections.
{
"cuid": "{END_USER_ID}",
"expt": 1735660800,
"mc": [
{
"mckey": "vnCVPVyV",
"seekable_end": 1,
"seek": false
}
]
}
Apply watermarking
An example security policy that displays the user ID (cuid) on screen for 3 seconds and hides it for 300 seconds (5 minutes).
{
"cuid": "{END_USER_ID}",
"expt": 1735660800,
"video_watermarking_code_policy": {
"code_kind": "client_user_id",
"font_size": 10,
"font_color": "FFFFFF",
"alpha": 128,
"show_time": 3,
"hide_time": 300
},
"mc": [
{
"mckey": "vnCVPVyV"
}
]
}
The full example code (PHP) is available in the Kollus GitHub repository.