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 URLvar drm = FairPlayConfig(certificateURLString: cert, licenseServerURLString: lic)!drm.tokenProvider = { request in // request.requestType is .initial or .renewal ["X-DRM-Token": await tokenService.freshToken()]}player.load({ url, drm: { widevine: { licenseUrl }, fairplay: { licenseUrl: fpLic, certificateUrl: cert }, tokenProvider: async ({ licenseUrl, renewal }) => ({ "X-DRM-Token": await freshToken(), }), },});<OGPlayerView style={{ flex: 1 }} source={{ url, drm: { widevine: { licenseUrl }, fairplay: { licenseUrl: fpLic, certificateUrl: cert }, tokenHeaderName: "X-DRM-Token", // renewal is accurate on iOS; always false on Android. tokenProvider: async ({ renewal }) => ({ "X-DRM-Token": await freshToken(), }), }, }}/>OGPlayerView( source: OGMediaItem( url: url, drm: DrmConfig( widevine: WidevineConfig(licenseUrl: licenseUrl), fairplay: FairPlayConfig(licenseUrl: fpLic, certificateUrl: cert), tokenHeaderName: 'X-DRM-Token', tokenProvider: (request) async => { // request.renewal is accurate on iOS; always false on Android. 'X-DRM-Token': await freshToken(), }, ), ),)The same on every platform
Section titled “The same on every platform”- 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.
What each platform does with the token
Section titled “What each platform does with the token”The platforms carry credentials differently, and OGPlayer follows each one’s own convention rather than flattening them:
| The provider returns | Where the token goes | Renewals | |
|---|---|---|---|
| Android | a token String | the single header you name in setTokenProvider("X-DRM-Token") { … }, or {token} in the license URL via setUrlTokenProvider | the provider is called again; the request does not distinguish a renewal |
| iOS | a [String: String] dictionary | every pair is set on the request, over any static headers | request.requestType is .initial or .renewal |
| Web | a Record<string, string> | every pair is set on the request, over any static headers | request.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 on the web
Section titled “DASH on the web”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).
React Native and Flutter
Section titled “React Native and Flutter”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
renewalis accurate. - On Android the token is sent in
tokenHeaderName, which is required there; any other key you return is not sent, andrenewalis alwaysfalse.
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.
FairPlay leases (iOS)
Section titled “FairPlay leases (iOS)”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 leasedrm: { fairplay: { certificateUrl: cert, licenseUrl: lic, renewalInterval: 55 }, // seconds tokenHeaderName: 'X-DRM-Token', tokenProvider: async () => ({ 'X-DRM-Token': await freshToken() }),}FairPlayConfig( certificateUrl: cert, licenseUrl: lic, renewalInterval: const Duration(seconds: 55),)Leave it unset (the default) for servers that issue keys without a lease.