Skip to main content
View as Markdown

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
  1. Get a widget session — an unprivileged KS that identifies your partner
  2. Compute the token hash — HASH(widget_ks + token_value) using the token's hash algorithm
  3. Exchange for a privileged KS — appToken.startSession validates the hash and returns a scoped KS

appToken.startSession​

POST /api_v3/service/appToken/action/startSession
ParameterTypeRequiredDescription
ksstringYesThe widget session KS (from startWidgetSession)
idstringYesAppToken ID
tokenHashstringYesHASH(widget_ks + token_value) — see section below for computation
userIdstringNoUser ID for the session (overridden by token's sessionUserId if set)
typeintNoSession type: 0=USER, 2=ADMIN (overridden by token's sessionType)
expiryintNoSession TTL in seconds (capped by token's sessionDuration)
sessionPrivilegesstringNoAdditional 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"
}