HMAC Session Flow - Authentication
Starting a Session with AppToken (HMAC Flow)
This is the core flow for integrations that use AppTokens instead of admin secrets.
The Three-Step Flow
session.startWidgetSession → HMAC(widget_ks + token_value) → appToken.startSession
- Get a widget session — an unprivileged KS that identifies your partner
- Compute the token hash —
HASH(widget_ks + token_value)using the token's hash algorithm - Exchange for a privileged KS —
appToken.startSessionvalidates the hash and returns a scoped KS
appToken.startSession
POST /api_v3/service/appToken/action/startSession
| Parameter | Type | Required | Description |
|---|---|---|---|
ks | string | Yes | The widget session KS (from startWidgetSession) |
id | string | Yes | AppToken ID |
tokenHash | string | Yes | HASH(widget_ks + token_value) — see section below for computation |
userId | string | No | User ID for the session (overridden by token's sessionUserId if set) |
type | int | No | Session type: 0=USER, 2=ADMIN (overridden by token's sessionType) |
expiry | int | No | Session TTL in seconds (capped by token's sessionDuration) |
sessionPrivileges | string | No | Additional privileges (merged with token's sessionPrivileges) |
Response: A JSON object containing the privileged KS string:
{
"ks": "djJ8MTIzNDU2fHh4eHh4eHh4...",
"objectType": "KalturaSessionInfo"
}
Computing the Token Hash
The tokenHash is computed by concatenating the widget KS and the AppToken's token value, then hashing the result with the algorithm matching the token's hashType.
Formula: tokenHash = HASH_ALGORITHM( WIDGET_KS + APP_TOKEN_VALUE )
The input is the raw string concatenation (no separator, no encoding) of the widget KS followed by the token value. The output is the lowercase hex digest.
Shell examples by hash type:
# SHA256 (recommended)
TOKEN_HASH=$(echo -n "$\{WIDGET_KS\}$\{APP_TOKEN_VALUE\}" | shasum -a 256 | cut -d' ' -f1)
# SHA1
TOKEN_HASH=$(echo -n "$\{WIDGET_KS\}$\{APP_TOKEN_VALUE\}" | shasum -a 1 | cut -d' ' -f1)
# SHA512
TOKEN_HASH=$(echo -n "$\{WIDGET_KS\}$\{APP_TOKEN_VALUE\}" | shasum -a 512 | cut -d' ' -f1)
# MD5
TOKEN_HASH=$(echo -n "$\{WIDGET_KS\}$\{APP_TOKEN_VALUE\}" | md5sum | cut -d' ' -f1)
The echo -n flag is critical — it ensures the hash input contains only the raw concatenated string with no trailing newline.
Complete curl Example
# --- Step 1: Get a widget session (unprivileged) ---
WIDGET_RESPONSE=$(curl -s -X POST "$KALTURA_SERVICE_URL/service/session/action/startWidgetSession" \
-d "widgetId=_$KALTURA_PARTNER_ID" \
-d "format=1")
WIDGET_KS=$(echo "$WIDGET_RESPONSE" | jq -r '.ks')
# --- Step 2: Compute the token hash (SHA256) ---
TOKEN_HASH=$(echo -n "$\{WIDGET_KS\}$\{APP_TOKEN_VALUE\}" | shasum -a 256 | cut -d' ' -f1)
# --- Step 3: Exchange for a privileged KS ---
SESSION_RESPONSE=$(curl -s -X POST "$KALTURA_SERVICE_URL/service/appToken/action/startSession" \
-d "ks=$WIDGET_KS" \
-d "format=1" \
-d "id=$APP_TOKEN_ID" \
-d "tokenHash=$TOKEN_HASH" \
-d "userId=integration-user" \
-d "type=0" \
-d "expiry=86400")
PRIVILEGED_KS=$(echo "$SESSION_RESPONSE" | jq -r '.ks')
# --- Use the privileged KS for API calls ---
curl -X POST "$KALTURA_SERVICE_URL/service/media/action/list" \
-d "ks=$PRIVILEGED_KS" \
-d "format=1" \
-d "pager[pageSize]=5"
Response (Step 1 — session.startWidgetSession):
{
"ks": "djJ8MTIzNDU2fDlhN...",
"partnerId": 123456,
"userId": "0",
"objectType": "KalturaStartWidgetSessionResponse"
}
Response (Step 3 — appToken.startSession):
{
"ks": "djJ8MTIzNDU2fHh4eHh4eHh4...",
"objectType": "KalturaSessionInfo"
}