Day 1 · 18 min read

Best Practices & Security

Studio expectations, common integration mistakes, security posture.

What "best practice" means in this context

Studios audit CWIPs. The audit looks for both technical correctness and operational hygiene. This module collects the recommendations Widevine engineers and content owners flag most often when reviewing real integrations.

Network and transport

Server-side checks

When a licence request hits your service:

  1. Authenticate the caller (session cookie, OAuth, signed app token).
  2. Check entitlement: does this user have the right to this content right now?
  3. Check device tier: are we issuing UHD policy or SD policy?
  4. Build the policy.
  5. Hand the request blob + policy to the SDK; return the SDK's response.
# Server-side sketch (deliberately abstract; real SDK calls in Day 2)
def issue_license(req_bytes, app_token):
    user = verify_app_token(app_token)        # 1
    entitlement = check_entitlement(user, req_bytes.content_id)  # 2
    if not entitlement:
        return 403
    policy = build_policy(entitlement, user.device_tier)         # 3 + 4
    return sdk.process_license_request(req_bytes, policy)        # 5

What to log

Studios sometimes ask for proof. The minimum bar:

  • License-issue rate per content per minute.
  • Per-device-tier breakdown of issued licences.
  • Per-error-code rate (invalid-token, unsupported-system, denied-by-policy).
  • Provisioning request volumes (anomalies = compromise indicator).

Don't log content keys, even hashed. Don't log full licence bytes. Studios audit what you log.

Common integration mistakes

Common pitfall

Sending content keys in URL parameters. Astonishingly common in early integrations and instantly disqualifying. The licence is the only legitimate path for keys.

Common pitfall

Ignoring renewal messages. Playback works in your tests because you never play long enough to trigger renewal. Production playback fails after the licence-renewal window.

Common pitfall

Caching the licence response per content. Each request is bound to the requesting CDM's session keys; the response is not reusable across devices.

Common pitfall

Using the same KID for SD/HD/UHD. Removes the ability to enforce per-resolution policies. Always per-resolution KIDs for premium content.

Common pitfall

Treating provisioning failures as fatal. Use exponential back-off. The provisioning service is rate-limited; aggressive retries across a fleet look like an attack.

Device fleet hygiene

  • Test on at least one L1 device per major SoC family (Snapdragon, Mediatek, Exynos for phones; whatever set-top boxes your audience uses).
  • Test on at least one L3 device.
  • Test on Chrome desktop (Linux, macOS, Windows) and Edge.
  • Re-test after major Chrome / Android releases — the CDM updates separately from the OS.
  • Keep an inventory of OEMCrypto version per device class.

Security posture for the licence service

  • Run the SDK behind your own auth layer; never expose the SDK port directly to the internet.
  • Rotate any signing material (app tokens, session keys) on a defined schedule.
  • Have a revocation plan: how do you stop issuing licences for a particular user / device / content?
  • Patch promptly — security CVEs in the SDK or OEMCrypto get disclosed; CWIPs are expected to apply them.
No questions yet for best-practices. Add some in content/questions/best-practices.json.