Skip to content

DRM tokens & license renewal

Most DRM deployments authorize license requests with short-lived tokens. Give OGPlayer a token provider and it fetches a fresh token on every license request — renewals included — so playback survives long pauses and license expiry without your code doing anything.

There is no standard header for DRM tokens — every vendor defines their own (x-dt-auth-token, x-vudrm-token, a bearer Authorization, …). Use whatever name your license server expects; the examples below use X-DRM-Token.

DrmConfig.Builder(licenseUrl)
.setTokenProvider("X-DRM-Token") { tokenService.freshToken() } // suspend fun
.build()
// URL-embedded tokens: .setUrlTokenProvider { ... } with {token} in the URL
  • The provider runs on every license request, renewals included — a token is never captured once and reused.
  • A provider failure surfaces as 4002 DRM_TOKEN_FETCH_FAILED (retryable).
  • Successful renewals fire onDrmSessionRenewed(reason) — your signal that a long-running session quietly refreshed.

The platforms carry credentials differently, and OGPlayer follows each one’s own convention rather than flattening them:

The provider returnsWhere the token goesRenewals
Androida token Stringthe single header you name in setTokenProvider("X-DRM-Token") { … }, or {token} in the license URL via setUrlTokenProviderthe provider is called again; the request does not distinguish a renewal
iOSa [String: String] dictionaryevery pair is set on the request, over any static headersrequest.requestType is .initial or .renewal
Weba Record<string, string>every pair is set on the request, over any static headersrequest.renewal is true on a renewal

Android names the header up front because its token is a single credential; iOS and Web hand you the whole header set. Both are the idiomatic shape for their platform.

Scheme coverage follows the platform too: on Android the provider serves Widevine, PlayReady and ClearKey; on iOS it serves FairPlay; on Web it serves whichever scheme the browser selected.

DASH items take the same provider as HLS: it runs on every license request, renewal is true on a renewal, and every pair it returns is set on the request to whichever scheme — Widevine or PlayReady — the CDM selected:

player.load({
url: "https://example.com/protected.mpd",
drm: {
widevine: { licenseUrl },
playready: { licenseUrl: prLicenseUrl },
tokenProvider: async ({ licenseUrl, renewal }) => ({
"X-DRM-Token": await freshToken(),
}),
},
});

Tizen and webOS apps run the same code on the TV bundle; packaged apps ship the DASH engine file ogplayer.dash.global.js next to ogplayer.tv.global.js (see the smart TV quick start).

One API spans both platforms, so it takes the broader shape — a map — and each side applies what it can:

  • On iOS every header you return is sent, and renewal is accurate.
  • On Android the token is sent in tokenHeaderName, which is required there; any other key you return is not sent, and renewal is always false.

If you need more than one credential header, or you branch on renewal, write that path against iOS and keep Android to the single named token.

Widevine renews an expiring license inside the CDM. FairPlay has no equivalent: a leased key simply stops working when the lease ends unless the app renews it. If your license server leases FairPlay keys for a fixed time, set renewalInterval a little under the lease and the SDK renews the key in the background before it expires — through your token provider, with onDrmSessionRenewed(.proactive) on each renewal:

var drm = FairPlayConfig(certificateURLString: cert, licenseServerURLString: lic,
renewalInterval: 55)! // 60 s lease

Leave it unset (the default) for servers that issue keys without a lease.