To enforce dual-token authentication when viewers access a streaming resource, you configure separate routes. A route is a configuration that matches requests for Media CDN and directs HTTP traffic to an origin. Media CDN supports routes for either HTTP live streaming (HLS) or Dynamic Adaptive Streaming over HTTP (DASH) resources. For more information, see Advanced routing.
For HLS streams, Media CDN supports both cookie-based and cookieless dual-token authentication. For DASH streams, Media CDN supports only cookie-based dual-token authentication.
This page describes how to configure Media CDN routes to help protect content using dual-token authentication.
Before you begin
Do the following:
Choose which signature method you're using for short-duration tokens: Ed25519 signatures or symmetric-key hash-based message authentication codes (HMACs).
You can turn on symmetric HMAC signing algorithms only for routes configured to generate new long-duration tokens. For optimal performance and security, we recommend that you use Ed25519 signatures, and use symmetric-key HMACs when necessary for compatibility with other CDNs.
The
EdgeCacheKeyset
that you configure for verifying signed request tokens must include the correct keys for the signature algorithm that you choose. The following table describes each of the signature algorithms and their required keys.signatureAlgorithm Required keys in keyset Ed25519 publicKeys
HMAC-SHA1 validationSharedKeys
HMAC-SHA256 validationSharedKeys
Tokens must be signed or verified with keys in
EdgeCacheKeysets
. As a best practice, make two separate keysets, one each for your short-duration tokens and long-duration tokens.If you are using DASH and using dynamic multimedia presentation description (MPD) files, you must use the same keyset for both the long and the short tokens.
Choose one of the following token formats for the long-duration tokens:
- Cookies
- URI query parameters
Set up short-duration tokens
Do the following:
Ed25519 signature
Run the following command to generate a private key:
openssl genpkey -algorithm ed25519 -outform PEM -out SSL_KEY_NAME.private.key
Replace
SSL_KEY_NAME
with the key name that you want.Run the following command to generate a public key from the private key you generated:
openssl pkey -outform DER -pubout -in SSL_KEY_NAME.private.key |\ tail -c +13 |\ python3 -c "import base64, sys; print(('%s' % base64.urlsafe_b64encode(sys.stdin.buffer.read()))[2:-1])"
For more information, see Create keys.
-
Create a new keyset with a single public key by doing the following:
Console
- Go to the Media CDN page in the Google Cloud console.
Go to Media CDN - Click the Keysets tab.
- Click Create keyset.
- In the Name field, enter keyset name—for example,
prod-vod-keyset
. - Optional: Add a description for your keyset.
- Optional: Add one or more labels for your keyset.
- In the ID field, enter an alpha-numeric ID, such as
first-key
. - In the Value enter your generated Ed25519 public key.
- Click Done.
gcloud CLI
gcloud edge-cache keysets create SHORT_KEYSET_NAME \ --public-key='id=SSL_PUBLIC_KEY_NAME,value=SSL_PUBLIC_KEY_VALUE'
Replace the following:
SHORT_KEYSET_NAME
: The keyset name that you wantSSL_PUBLIC_KEY_NAME
: The name of your SSL public keySSL_PUBLIC_KEY_VALUE
: The value of your SSL public key
The output is similar to the following:
[Keyset "prod-vod-keyset" created]
You can review the keys associated with a keyset by inspecting (describing) it by name:
gcloud edge-cache keysets describe prod-vod-keyset
The output is similar to the following:
name: prod-vod-keyset description: "Keyset for prod.example.com" publicKeys: - id: "key-20200918" value: "DThVLjhAKm3VYOvLBAwFZ5XbjVyF98Ias8NZU0WEM9w" - id: "key-20200808" value: "Lw7LDSaDUrbDdqpPA6JEmMF5BA5GPtd7sAjvsnh7uDA="
Terraform
- Go to the Media CDN page in the Google Cloud console.
Symmetric-key HMAC
If you haven't used Secret Manager before, configure Secret Manager.
Use Secret Manager to create a secret.
Use Secret Manager to add a secret version.
Ensure that the secret version that you add is in binary format.
Grant the Secret Manager Access role (
roles/secretmanager.secretAccessor
) to the Media CDN service account:Console
In the Google Cloud console, go to the Secret Manager page.
- On the Secret Manager page, select the checkbox next to the name of the secret.
- If it is not already open, click Show Info Panel to open the panel.
- In the info panel, click Add Principal.
In the New principals field, enter the Media CDN service account:
service-PROJECT_NUMBER@gcp-sa-mediaedgefill.iam.gserviceaccount.com
Replace
PROJECT_NUMBER
with your project number.- In the Select a role list, choose Secret Manager, and then choose Secret Manager Secret Accessor.
gcloud
gcloud secrets add-iam-policy-binding projects/PROJECT_NUMBER/secrets/SECRET_ID \ --member="serviceAccount:service-PROJECT_NUMBER@gcp-sa-mediaedgefill.iam.gserviceaccount.com" \ --role="roles/secretmanager.secretAccessor"
Replace the following:
PROJECT_NUMBER
: your project numberSECRET_ID
: the ID of the secret
Access your secret versions. Copy the secret paths, including version numbers.
Include the shared secrets in a Media CDN keyset:
gcloud edge-cache keysets create SHORT_KEYSET_NAME \ --validation-shared-key='secret_version=projects/PROJECT_NUMBER/secrets/SECRET_ID/versions/KEY_VERSION '
Replace the following:
SHORT_KEYSET_NAME
: the name of the keysetPROJECT_NUMBER
: your project IDSECRET_ID
: the ID of the secretKEY_VERSION
: the key version to use
The output is similar to the following:
[Keyset "SHORT_KEYSET_NAME" created]
Set up long-duration tokens
Google-managed keys are scoped by keyset. That means that two different keysets have different Google-managed keys. Google-managed keys are rotated regularly.
To create and set up a long-duration token, do one of the following:
Create a Google-managed signing key for long-duration tokens:
gcloud edge-cache keysets create LONG_KEYSET_NAME \ --public-key='id=google-managed-key,managed=true'
Replace
LONG_KEYSET_NAME
with a key name.Modify an existing keyset:
Export your keyset to a
.YAML
file:gcloud edge-cache keysets export LONG_KEYSET_NAME \ --destination=prod-vod-keyset-long.yaml
In a text editor or in your configuration management tooling, edit your keyset configuration to add a Google-managed file so that it looks similar to the following:
name: projects/my-project/locations/global/edgeCacheKeysets/LONG_KEYSET_NAME publicKeys: - id: some-key value: MC4CAQAwBQYDK2VwBCIEINV2iYugIWBuvGBJUQ_Ab69E4v4zcVqvgYHw-iZxGzcd - id: google-managed-key managed: true
Import the edited keyset:
gcloud edge-cache keysets import LONG_KEYSET_NAME \ --source=prod-vod-keyset-long.yaml
The output is similar to the following:
[imported LONG_KEYSET_NAME]
You can include additional public keys in the long-duration token keyset, with the following limitations:
- Three public keys maximum
- One Google-managed key maximum
In practice, this means that you can have two user-managed keys and one Google-managed key in a long-duration token keyset. Media CDN always uses the Google-managed key to generate tokens. The user-managed keys can be used only for verification.
Including additional public keys is useful for allowing your player application to access media playlists and media segments by using signed requests generated by your own private keys.
Create or export a configuration file
This section shows how to export or create a Media CDN configuration file, creating multiple routes. A route lets you optimize behavior based on the type of content, client attributes, and your freshness requirements. In the following examples, we use routes to configure token exchange for each part of a media request.
For more information on routes, see Advanced Routing.
If you have an existing Media CDN configuration, export your existing configuration and apply edits to the exported file. Otherwise, create a new file.
Export configuration
Export an existing configuration:
gcloud edge-cache services export SERVICE_NAME \
--destination=FILENAME.yaml
Replace the following:
SERVICE_NAME
: Your service's nameFILENAME
: The filename that you want
The output is similar to the following:
Exported [projects/my-project/locations/global/edgeCacheServices/SERVICE_NAME] to 'FILENAME.yaml'.
The content of the exported configuration file is similar to the following:
name: SERVICE_NAME
routing:
hostRules:
- hosts:
- DOMAIN_NAME
pathMatcher: routes
pathMatchers:
- name: routes
routeRules:
- priority: 1
matchRules:
- prefixMatch: /
origin: ORIGIN_NAME
routeAction:
cdnPolicy:
cacheMode: CACHE_ALL_STATIC
defaultTtl: 3600s
In this example:
SERVICE_NAME
: Your service's nameDOMAIN_NAME
: Your service's domain nameORIGIN_NAME
: The origin's name
For the following sections, apply edits to the configuration file you
downloaded, FILENAME
.yaml.
Make a configuration
Do the following:
Create a local file,
FILENAME
.yaml.Replace
FILENAME
with the filename that you want.Enter the following content into the file:
name: SERVICE_NAME routing: hostRules: - hosts: - DOMAIN_NAME pathMatcher: routes
Replace the following:
SERVICE_NAME
: Your service's nameDOMAIN_NAME
: Your service's domain name
For the following sections, apply edits to the configuration file you created,
FILENAME.yaml
.
Edit the configuration file
The following section shows how to edit the Media CDN configuration file for dual-token authentication.
Configure the primary manifest route to require short-duration tokens
Turn on token authentication on a route by specifying a signedTokensOptions
configuration in the route's Media CDN policy.
Edit the configuration file as follows:
Ed25519 signature
pathMatchers:
- name: "ROUTE_NAME"
routeRules:
- priority: 1
description: "ROUTE_DESCRIPTION"
origin: "ORIGIN_NAME"
matchRules:
- pathTemplateMatch: "/MANIFEST_OR_PLAYLIST"
routeAction:
cdnPolicy:
cacheMode: CACHE_ALL_STATIC
signedRequestMode: REQUIRE_TOKENS
signedRequestKeyset: SHORT_KEYSET_NAME
signedRequestMaximumExpirationTtl: SIGNED_REQUEST_MAXIMUM_EXPIRATION_TIME
signedTokenOptions:
tokenQueryParameter: SHORT_TOKEN_NAME
Replace the following:
ROUTE_NAME
: The name of the routeROUTE_DESCRIPTION
: The description of the routeORIGIN_NAME
: The origin nameMANIFEST_OR_PLAYLIST
: The name of the HLS primary playlist (.m3u8
) or DASH manifest (.mpd
) fileSHORT_KEYSET_NAME
: The keyset name to use for short-duration tokensSIGNED_REQUEST_MAXIMUM_EXPIRATION_TIME
: The expiration time for signed requests. For example,600s
. For more information, seesignedRequestMaximumExpirationTtl
.- Optional:
SHORT_TOKEN_NAME
: The query parameter in which to find the short token. The default value isedge-cache-token
. For more information, seeSignedTokenOptions
.
Symmetric-key HMAC
pathMatchers:
- name: "ROUTE_NAME"
routeRules:
- priority: 1
description: "ROUTE_DESCRIPTION"
origin: "ORIGIN_NAME"
matchRules:
- pathTemplateMatch: "/MANIFEST_OR_PLAYLIST"
routeAction:
cdnPolicy:
cacheMode: CACHE_ALL_STATIC
signedRequestMode: REQUIRE_TOKENS
signedRequestKeyset: SHORT_KEYSET_NAME
signedRequestMaximumExpirationTtl: SIGNED_REQUEST_MAXIMUM_EXPIRATION_TIME
signedTokenOptions:
tokenQueryParameter: SHORT_TOKEN_NAME
allowedSignatureAlgorithms:
- HMAC_SHA_256
Replace the following:
ROUTE_NAME
: The name of the routeROUTE_DESCRIPTION
: The description of the routeORIGIN_NAME
: The origin nameMANIFEST_OR_PLAYLIST
: The names or path templates for the HLS primary playlists (.m3u8
), DASH manifest (.mpd
) files, or both. For more information about path matching, see Path matching.SHORT_KEYSET_NAME
: The keyset name to use for short-duration tokensSIGNED_REQUEST_MAXIMUM_EXPIRATION_TIME
: The maximum expiration time for signed requests. For example,600s
. For more information, seesignedRequestMaximumExpirationTtl
.- Optional:
SHORT_TOKEN_NAME
: The query parameter in which to find the short token. The default value isedge-cache-token
. For more information, seeSignedTokenOptions
.
Modify the primary manifest route to generate long-duration tokens
Configure Media CDN to generate long-duration tokens on the primary manifest route.
Append your configuration file, by using either cookies or URL query parameters:
Cookies
addSignatures:
actions:
- GENERATE_COOKIE
keyset: LONG_KEYSET_NAME
tokenTtl: TOKEN_EXPIRATION_TIME
copiedParameters:
- PathGlobs
- SessionID
Replace the following:
LONG_KEYSET_NAME
: The name of your long-duration token keyset.TOKEN_EXPIRATION_TIME
: The expiration time of the long-duration token. For example,86400s
for a one day expiration time.
This code example implements the following changes:
addSignatures.actions: GENERATE_COOKIE
: Configures Media CDN to return anEdge-Cache-Cookie
with the primary manifest response.copiedParameters.PathGlobs
: configures Media CDN to copy thePathGlobs
from the short-duration token to the long-duration token. To use dual-token authentication, you must use one ofcopiedParameters.PathGlobs
orcopiedParameters.URLPrefix
.For more information, see
copiedParameters
.Optional:
copiedParameters.SessionID
: configures Media CDN to copy theSessionID
from the short-duration token to the long-duration token.
When the GENERATE_COOKIE
action is applied,
Media CDN returns a Set-Cookie
header similar to the following
with the primary manifest response:
Set-Cookie: Edge-Cache-Cookie=PathGlobs=PATHS~SessionID=SESSION_ID~Expires=EXPIRATION~_GO=Generated~Signature=SIGNATURE
URL query parameters
addSignatures:
actions:
- GENERATE_TOKEN_HLS_COOKIELESS
keyset: LONG_KEYSET_NAME
tokenTtl: TOKEN_EXPIRATION_TIME
copiedParameters:
- PathGlobs
- SessionID
tokenQueryParameter: LONG_TOKEN_NAME
Replace the following:
LONG_KEYSET_NAME
: The name of your long-duration keyset.TOKEN_EXPIRATION_TIME
: The expiration time of the long-duration token. For example,86400s
for a one day expiration time.
This code example implements the following changes:
addSignatures.actions: GENERATE_TOKEN_HLS_COOKIELESS
: Configures Media CDN to manipulate the HLS primary manifest by appending a long-duration token to each URI present.copiedParameters.PathGlobs
: configures Media CDN to copy thePathGlobs
from the short-duration token to the long-duration token. To use dual-token authentication, you must use one ofcopiedParameters.PathGlobs
orcopiedParameters.URLPrefix
.For more information, see
copiedParameters
.Optional:
copiedParameters.SessionID
: configures Media CDN to copy theSessionID
from the short-duration token to the long-duration token.Optional:
LONG_TOKEN_NAME
: The query parameter in which to put the generated long token. The default value isedge-cache-token
. For more information, seetokenQueryParameter
.
The following manifest file shows the GENERATE_TOKEN_HLS_COOKIELESS
action
applied:
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=1280000,AVERAGE-BANDWIDTH=1000000
http://example.com/HLS_PRIMARY_PLAYLIST.m3u8?LONG_TOKEN_NAME=PathGlobs=PATHS~SessionID=SESSION_ID~Expires=EXPIRATION~_GO=Generated~Signature=SIGNATURE
Media CDN generates and stores the long-duration token in the
LONG_TOKEN_NAME
query parameter after verifying the
short-duration token.
Configure subsequent routes
Configure subsequent routes for long-duration tokens. For cookies, you add an additional route to require long-duration tokens.
Cookies
Configure the media playlist and segments to require long-duration cookies
Edit the configuration file as follows:
- priority: 2
description: "SEGMENTS_ROUTE_DESCRIPTION"
origin: "ORIGIN_NAME"
matchRules:
- pathTemplateMatch: "/**.m3u8" # HLS media playlists
- pathTemplateMatch: "/**.ts" # HLS segments
- pathTemplateMatch: "/**.m4s" # DASH / CMAF segments
routeAction:
cdnPolicy:
cacheMode: CACHE_ALL_STATIC
signedRequestMode: REQUIRE_TOKENS
signedRequestKeyset: LONG_KEYSET_NAME
Replace SEGMENTS_ROUTE_DESCRIPTION with a description of the route.
This code example implements the following changes:
priority: 2
: Higher values indicate lower priority. Because the route for your media playlists and media segments matches any filename ending in.m3u8
, the priority for the route must be lower than the route you previously created for the primary manifest.signedRequestMode: REQUIRE_TOKENS
: Enforces tokens for media playlists and media segments.If you are using static media presentation description (MPD) files, the long and short keysets may be different. If you are using dynamic MPD files, then the long and short keysets must be the same.
signedRequestKeyset: LONG_KEYSET_NAME
: Media CDN uses the long-duration keyset to validate the long-duration cookie supplied by a user agent for media playlist and media segment requests.
URL query parameters
For URL query parameters, you add two route configurations to do the following:
- Configure the HLS media manifest to propagate long-duration tokens.
- Configure the segment routes to require long-duration tokens.
Configure the HLS media manifest routes to propagate long-duration tokens
Edit the configuration file as follows:
- priority: 2
description: "PLAYLIST_ROUTE_DESCRIPTION"
origin: "ORIGIN_NAME"
matchRules:
- pathTemplateMatch: "/**.m3u8" # HLS media playlists
routeAction:
cdnPolicy:
cacheMode: CACHE_ALL_STATIC
signedRequestMode: REQUIRE_TOKENS
signedRequestKeyset: LONG_KEYSET_NAME
addSignatures:
actions:
- PROPAGATE_TOKEN_HLS_COOKIELESS
Replace PLAYLIST_ROUTE_DESCRIPTION with a description of the route.
This code example implements the following changes:
priority: 2
: Higher values indicate lower priority. Because the route for your media playlists matches any filename ending in.m3u8
, the priority for the route must be lower than the route you previously created for the primary manifest.signedRequestMode: REQUIRE_TOKENS
: Enforces tokens for media playlists and media segments.If you are using static media presentation description (MPD) files, the long and short keysets may be different. If you are using dynamic MPD files, then the long and short keysets must be the same.
signedRequestKeyset: LONG_KEYSET_NAME
: Media CDN uses the long-duration keyset to validate the long-duration cookie supplied by a user agent for media playlist and media segment requests.addSignatures.actions: PROPAGATE_TOKEN_HLS_COOKIELESS
: Configures Media CDN to copy the long-duration token to media segment URIs in the media playlists.
Configure the segment routes to require long-duration tokens
Edit the configuration file as follows:
- priority: 3
description: "SEGMENTS_ROUTE_DESCRIPTION"
origin: "ORIGIN_NAME"
matchRules:
- pathTemplateMatch: "/**.ts" # HLS segments
routeAction:
cdnPolicy:
cacheMode: CACHE_ALL_STATIC
signedRequestMode: REQUIRE_TOKENS
signedRequestKeyset: LONG_KEYSET_NAME
Replace SEGMENTS_ROUTE_DESCRIPTION with a description of the route.
This code example implements the following changes:
priority: 3
: Higher values indicate lower priority. Route priorities must be unique.signedRequestMode: REQUIRE_TOKENS
: Enforces tokens for media playlists and media segments.signedRequestKeyset: LONG_KEYSET_NAME
: Media CDN uses the long-duration keyset to validate the long-duration signed token supplied by a user agent for media playlist and media segment requests.
Example completed file
The following code sample shows a completed configuration file:
Cookies
name: SERVICE_NAME
routing:
hostRules:
- hosts:
- DOMAIN_NAME
pathMatcher: routes
pathMatchers:
- name: "ROUTE_NAME"
routeRules:
- priority: 1
description: "ROUTE_DESCRIPTION"
origin: "ORIGIN_NAME"
matchRules:
- pathTemplateMatch: "/HLS_MASTER_PLAYLIST.m3u8" # HLS primary playlists
- pathTemplateMatch: "/DASH_MANIFESTS.mpd" # DASH manifests
routeAction:
cdnPolicy:
cacheMode: CACHE_ALL_STATIC
signedRequestMode: REQUIRE_TOKENS
signedRequestKeyset: SHORT_KEYSET_NAME
signedRequestMaximumExpirationTtl: SIGNED_REQUEST_MAXIMUM_EXPIRATION_TIME
addSignatures:
actions:
- GENERATE_COOKIE
keyset: LONG_KEYSET_NAME
tokenTtl: TOKEN_EXPIRATION_TIME
copiedParameters:
- PathGlobs
- SessionID
- priority: 2
description: "SEGMENTS_ROUTE_DESCRIPTION"
origin: "ORIGN_NAME"
matchRules:
- pathTemplateMatch: "/**.m3u8" # HLS media playlists
- pathTemplateMatch: "/**.ts" # HLS segments
- pathTemplateMatch: "/**.m4s" # DASH / CMAF segments
routeAction:
cdnPolicy:
cacheMode: CACHE_ALL_STATIC
signedRequestMode: REQUIRE_TOKENS
signedRequestKeyset: LONG_KEYSET_NAME
URL query parameters
name: SERVICE_NAME
routing:
hostRules:
- hosts:
- DOMAIN_NAME
pathMatcher: routes
pathMatchers:
- name: "ROUTE_NAME"
routeRules:
- priority: 1
description: "ROUTE_DESCRIPTION"
origin: "ORIGIN_NAME"
matchRules:
- pathTemplateMatch: "/HLS_PRIMARY_PLAYLIST.m3u8" # HLS primary playlists
routeAction:
cdnPolicy:
cacheMode: CACHE_ALL_STATIC
signedRequestMode: REQUIRE_TOKENS
signedRequestKeyset: SHORT_KEYSET_NAME
signedRequestMaximumExpirationTtl: SIGNED_REQUEST_MAXIMUM_EXPIRATION_TIME
signedTokenOptions:
tokenQueryParameter: SHORT_TOKEN_NAME
addSignatures:
actions:
- GENERATE_TOKEN_HLS_COOKIELESS
keyset: LONG_KEYSET_NAME
tokenTtl: TOKEN_EXPIRATION_TIME
tokenQueryParameter: LONG_TOKEN_NAME
copiedParameters:
- PathGlobs
- SessionID
- priority: 2
description: "PLAYLIST_ROUTE_DESCRIPTION"
origin: "ORIGIN_NAME"
matchRules:
- pathTemplateMatch: "/**.m3u8" # HLS media playlists
routeAction:
cdnPolicy:
cacheMode: CACHE_ALL_STATIC
signedRequestMode: REQUIRE_TOKENS
signedRequestKeyset: LONG_KEYSET_NAME
addSignatures:
actions:
- PROPAGATE_TOKEN_HLS_COOKIELESS
- priority: 3
description: "SEGMENTS_ROUTE_DESCRIPTION"
origin: "ORIGIN_NAME"
matchRules:
- pathTemplateMatch: "/**.ts" # HLS segments
routeAction:
cdnPolicy:
cacheMode: CACHE_ALL_STATIC
signedRequestMode: REQUIRE_TOKENS
signedRequestKeyset: LONG_KEYSET_NAME
Import the edited configuration file
Apply your configuration changes and turn on dual-token authentication:
gcloud edge-cache services import SERVICE_NAME --source=FILENAME.yaml
Generate short-duration tokens at your application server
For information about generating tokens, see Generate tokens.
Apply defense-in-depth content protections
As a best practice, turn on origin authentication, as follows:
For Cloud Storage, use Identity and Access Management permissions with private Cloud Storage buckets.
For AWS-compatible storage providers, use AWS Signature Version 4. Using origin authentication blocks requests that attempt to circumvent Media CDN and access your origin directly.