Embed Token vs Signed URL — Two Patterns for Video Access Control

Embed Token vs Signed URL

Two patterns for controlling who can play a video: opaque embed tokens (server-side lookup) and signed URLs (HMAC-signed query strings). Both are common; they have different trade-offs.

Embed tokens (opaque)

A short opaque string that maps server-side to access metadata: video ID, allowed origins, expiration, viewer ID for watermark, rate limits.

Pros:

  • Real-time revocation — invalidate the token in DB and the next key fetch fails.
  • Rich metadata — analytics per token, custom rate limits, dynamic watermark binding.
  • Short, clean URLs — /watch/abc123.

Cons:

  • Server-side state — every key fetch validates the token via DB lookup.
  • Slightly higher latency on uncached lookups.

Used by: AVCaption.

Signed URLs (HMAC)

A URL with a cryptographic signature appended: /segment.ts?expires=1735689600&sig=abcdef.... The signature is computed by the platform server using a secret key, and verified at the edge — no DB lookup needed.

Pros:

  • Stateless — verifiable at CDN edge with no server roundtrip.
  • Fast — cryptographic check is microseconds.

Cons:

  • No revocation — once signed, valid until expiration.
  • Less metadata — what you can encode in URL params.
  • Longer URLs.

Used by: AWS S3 presigned URLs, CloudFront signed URLs, Cloudflare Stream signed URLs.

When each makes sense

Embed token (opaque) is right when:

  • You need to revoke access after issue (refunds, account suspension)
  • You want per-viewer analytics or dynamic watermark
  • You want short clean URLs for embedding

Signed URL is right when:

  • You operate at massive scale where DB lookup overhead matters
  • Revocation isn’t a requirement (short expiration is enough)
  • Your delivery layer (CDN edge) verifies signatures natively

For paid courses and gated content, opaque embed tokens are the better fit. For one-off public content distribution, signed URLs are simpler.

AVCaption uses opaque tokens with optional per-session generation via REST API for dynamic access control.

← content.back_to_index