The concept behind URI Signing is based on embedding a signed [
RFC 7519] in an [
RFC 7230] (see
Section 2.7 of
RFC 7230). The signed JWT contains a number of claims that can be verified to ensure the UA has legitimate access to the content.
This document specifies the following attribute for embedding a signed JWT in a Target CDN URI or Redirection URI:
-
URI Signing Package (URISigningPackage):
-
The URI attribute that encapsulates all the URI Signing claims in a signed JWT encoded format. This attribute is exposed in the Signed URI as a path-style parameter or a form-style parameter.
The parameter name of the URI Signing Package Attribute is defined in the
Section 4.4. If the CDNI Metadata interface is not used, or does not include a parameter name for the URI Signing Package Attribute, the parameter name can be set by configuration (out of scope of this document).
The URI Signing Package will be found by parsing any path-style parameters and form-style parameters looking for a key name matching the URI Signing Package Attribute. Both parameter styles
MUST be supported to allow flexibility of operation. The first matching parameter
SHOULD be taken to provide the signed JWT, though providing more than one matching key is undefined behavior. Path-style parameters generated in the form indicated by
Section 3.2.7 of
RFC 6570 and Form-style parameters generated in the form indicated by Sections
3.2.8 and
3.2.9 of [
RFC 6570]
MUST be supported.
The following is an example where the URI Signing Package Attribute name is "token" and the signed JWT is "SIGNEDJWT":
http://example.com/media/path?come=data&token=SIGNEDJWT&other=data
This section identifies the set of claims that can be used to enforce the CSP distribution policy. New claims can be introduced in the future to extend the distribution policy capabilities.
In order to provide distribution policy flexibility, the exact subset of claims used in a given signed JWT is a runtime decision. Claim requirements are defined in the
Section 4.4. If the CDNI Metadata interface is not used, or does not include claim requirements, the claim requirements can be set by configuration (out of scope of this document).
The following claims (where the "JSON Web Token Claims" registry claim name is specified in parentheses below) are used to enforce the distribution policies. All of the listed claims are mandatory to implement in a URI Signing implementation but are not necessarily mandatory to use in a given signed JWT. (The "optional" and "mandatory" identifiers in square brackets refer to whether or not a given claim
MUST be present in a URI Signing JWT.)
Note: The time on the entities that generate and verify the Signed URI
MUST be in sync. In the CDNI case, this means that CSP, uCDN, and dCDN servers need to be time synchronized. It is
RECOMMENDED to use [
RFC 5905] for time synchronization.
Note: See the
Section 7 on the limitations of using an expiration time and Client IP address for distribution policy enforcement.
Issuer (iss) [optional] - The semantics in
Section 4.1.1 of
RFC 7519 MUST be followed. If this claim is used, it
MUST be used to identify the Issuer (signer) of the JWT. In particular, the recipient will have already received, in trusted configuration, a mapping of Issuer name to one or more keys used to sign JWTs and must verify that the JWT was signed by one of those keys. If this claim is used and the CDN verifying the signed JWT does not support Issuer verification, or if the Issuer in the signed JWT does not match the list of known acceptable Issuers, or if the Issuer claim does not match the key used to sign the JWT, the CDN
MUST reject the request. If the received signed JWT contains an Issuer claim, then any JWT subsequently generated for CDNI redirection
MUST also contain an Issuer claim, and the Issuer value
MUST be updated to identify the redirecting CDN. If the received signed JWT does not contain an Issuer claim, an Issuer claim
MAY be added to a signed JWT generated for CDNI redirection.
Subject (sub) [optional] - The semantics in
Section 4.1.2 of
RFC 7519 MUST be followed. If this claim is used, it
MUST be a JSON Web Encryption ([
RFC 7516]) Object in compact serialization form, because it contains personally identifiable information. This claim contains information about the Subject (for example, a user or an agent) that
MAY be used to verify the signed JWT. If the received signed JWT contains a Subject claim, then any JWT subsequently generated for CDNI redirection
MUST also contain a Subject claim, and the Subject value
MUST be the same as in the received signed JWT. A signed JWT generated for CDNI redirection
MUST NOT add a Subject claim if no Subject claim existed in the received signed JWT.
Audience (aud) [optional] - The semantics in
Section 4.1.3 of
RFC 7519 MUST be followed. This claim is used to ensure that the CDN verifying the JWT is an intended recipient of the request. The claim
MUST contain an identity belonging to the chain of entities involved in processing the request (e.g., identifying the CSP or any CDN in the chain) that the recipient is configured to use for the processing of this request. A CDN
MAY modify the claim as long it can generate a valid signature.
Expiry Time (exp) [optional] - The semantics in
Section 4.1.4 of
RFC 7519 MUST be followed, though URI Signing implementations
MUST NOT allow for any time-synchronization "leeway". If this claim is used and the CDN verifying the signed JWT does not support Expiry Time verification, or if the Expiry Time in the signed JWT corresponds to a time equal to or earlier than the time of the content request, the CDN
MUST reject the request. If the received signed JWT contains an Expiry Time claim, then any JWT subsequently generated for CDNI redirection
MUST also contain an Expiry Time claim, and the Expiry Time value
MUST be the same as in the received signed JWT. A signed JWT generated for CDNI redirection
MUST NOT add an Expiry Time claim if no Expiry Time claim existed in the received signed JWT.
Not Before (nbf) [optional] - The semantics in
Section 4.1.5 of
RFC 7519 MUST be followed, though URI Signing implementations
MUST NOT allow for any time-synchronization "leeway". If this claim is used and the CDN verifying the signed JWT does not support Not Before time verification, or if the Not Before time in the signed JWT corresponds to a time later than the time of the content request, the CDN
MUST reject the request. If the received signed JWT contains a Not Before time claim, then any JWT subsequently generated for CDNI redirection
MUST also contain a Not Before time claim, and the Not Before time value
MUST be the same as in the received signed JWT. A signed JWT generated for CDNI redirection
MUST NOT add a Not Before time claim if no Not Before time claim existed in the received signed JWT.
Issued At (iat) [optional] - The semantics in
Section 4.1.6 of
RFC 7519 MUST be followed. If the received signed JWT contains an Issued At claim, then any JWT subsequently generated for CDNI redirection
MUST also contain an Issued At claim, and the Issued At value
MUST be updated to identify the time the new JWT was generated. If the received signed JWT does not contain an Issued At claim, an Issued At claim
MAY be added to a signed JWT generated for CDNI redirection.
JWT ID (jti) [optional] - The semantics in
Section 4.1.7 of
RFC 7519 MUST be followed. A JWT ID can be used to prevent replay attacks if the CDN stores a list of all previously used values and verifies that the value in the current JWT has never been used before. If the signed JWT contains a JWT ID claim and the CDN verifying the signed JWT either does not support JWT ID storage or has previously seen the value used in a request for the same content, then the CDN
MUST reject the request. If the received signed JWT contains a JWT ID claim, then any JWT subsequently generated for CDNI redirection
MUST also contain a JWT ID claim, and the value
MUST be the same as in the received signed JWT. If the received signed JWT does not contain a JWT ID claim, a JWT ID claim
MUST NOT be added to a signed JWT generated for CDNI redirection. Sizing of the JWT ID is application dependent given the desired security constraints.
CDNI Claim Set Version (cdniv) [optional] - The CDNI Claim Set Version (cdniv) claim provides a means within a signed JWT to tie the claim set to a specific version of this specification. The cdniv claim is intended to allow changes in and facilitate upgrades across specifications. The type is a JSON integer and the value
MUST be set to "1" for this version of the specification. In the absence of this claim, the value is assumed to be "1". For future versions, this claim will be mandatory. Implementations
MUST reject signed JWTs with unsupported CDNI Claim Set versions.
CDNI Critical Claims Set (cdnicrit) [optional] - The CDNI Critical Claims Set (cdnicrit) claim indicates that extensions to this specification are being used that
MUST be understood and processed. Its value is a comma-separated listing of claims in the Signed JWT that use those extensions. If any of the listed extension claims are not understood and supported by the recipient, then the Signed JWT
MUST be rejected. Producers
MUST NOT include claim names defined by this specification, duplicate names, or names that do not occur as claim names within the Signed JWT in the cdnicrit list. Producers
MUST NOT use the empty list "" as the cdnicrit value. Recipients
MAY consider the Signed JWT to be invalid if the cdnicrit list contains any claim names defined by this specification or if any other constraints on its use are violated. This claim
MUST be understood and processed by all implementations.
Client IP Address (cdniip) [optional] - The Client IP Address (cdniip) claim holds an IP address or IP prefix for which the Signed URI is valid. This is represented in CIDR notation with dotted decimal format for [
RFC 0791] or canonical text representation for [
RFC 5952]. The request
MUST be rejected if sourced from a client outside the specified IP range. Since the Client IP is considered personally identifiable information, this field
MUST be a JSON Web Encryption ([
RFC 7516]) Object in compact serialization form. If the CDN verifying the signed JWT does not support Client IP verification, or if the Client IP in the signed JWT does not match the source IP address in the content request, the CDN
MUST reject the request. The type of this claim is a JSON string that contains the JWE. If the received signed JWT contains a Client IP claim, then any JWT subsequently generated for CDNI redirection
MUST also contain a Client IP claim, and the Client IP value
MUST be the same as in the received signed JWT. A signed JWT generated for CDNI redirection
MUST NOT add a Client IP claim if no Client IP claim existed in the received signed JWT.
It should be noted that use of this claim can cause issues, for example, in situations with dual-stack IPv4 and IPv6 networks, MPTCP, QUIC, and mobile clients switching from Wi-Fi to Cellular networks where the client's source address can change, even between address families. This claim exists mainly for legacy feature parity reasons; therefore, use of this claim should be done judiciously. An example of a reasonable use case would be making a signed JWT for an internal preview of an asset where the end consumer understands that they must be originated from the same IP for the entirety of the session. Using this claim at large is
NOT RECOMMENDED.
URI Container (cdniuc) [mandatory] - The URI Container (cdniuc) holds the URI representation before a URI Signing Package is added. This representation can take one of several forms detailed in
Section 2.1.15. If the URI Container used in the signed JWT does not match the URI of the content request, the CDN verifying the signed JWT
MUST reject the request. When comparing the URI, the percent encoded form as defined in
Section 2.1 of
RFC 3986 MUST be used. When redirecting a URI, the CDN generating the new signed JWT
MAY change the URI Container to comport with the URI being used in the redirection.
CDNI Expiration Time Setting (cdniets) [optional] - The CDNI Expiration Time Setting (cdniets) claim provides a means for setting the value of the Expiry Time (exp) claim when generating a subsequent signed JWT in Signed Token Renewal. Its type is a JSON numeric value. It denotes the number of seconds to be added to the time at which the JWT is verified that gives the value of the Expiry Time (exp) claim of the next signed JWT. The CDNI Expiration Time Setting (cdniets)
SHOULD NOT be used when not using Signed Token Renewal and
MUST be present when using Signed Token Renewal.
CDNI Signed Token Transport (cdnistt) [optional] - The CDNI Signed Token Transport (cdnistt) claim provides a means of signaling the method through which a new signed JWT is transported from the CDN to the UA and vice versa for the purpose of Signed Token Renewal. Its type is a JSON integer. Values for this claim are defined in
Section 6.5. If using this claim, you
MUST also specify a CDNI Expiration Time Setting (cdniets) as noted above.
CDNI Signed Token Depth (cdnistd) [optional] - The CDNI Signed Token Depth (cdnistd) claim is used to associate a subsequent signed JWT, generated as the result of a CDNI Signed Token Transport claim, with a specific URI subset. Its type is a JSON integer. Signed JWTs
MUST NOT use a negative value for the CDNI Signed Token Depth claim.
If the transport used for Signed Token Transport allows the CDN to associate the path component of a URI with tokens (e.g., an HTTP Cookie Path as described in
Section 4.1.2.4 of
RFC 6265), the CDNI Signed Token Depth value is the number of path segments that should be considered significant for this association. A CDNI Signed Token Depth of zero means that the client
SHOULD be directed to return the token with requests for any path. If the CDNI Signed Token Depth is greater than zero, then the CDN
SHOULD send the client a token to return for future requests wherein the first CDNI Signed Token Depth segments of the path match the first CDNI Signed Token Depth segments of the Signed URI path. This matching
MUST use the URI with the token removed, as specified in
Section 2.1.15.
If the URI path to match contains fewer segments than the CDNI Signed Token Depth claim, a signed JWT
MUST NOT be generated for the purposes of Signed Token Renewal. If the CDNI Signed Token Depth claim is omitted, it means the same thing as if its value were zero. If the received signed JWT contains a CDNI Signed Token Depth claim, then any JWT subsequently generated for CDNI redirection or Signed Token Transport
MUST also contain a CDNI Signed Token Depth claim, and the value
MUST be the same as in the received signed JWT.
The URI Container (cdniuc) claim takes one of the following forms: 'hash:' or 'regex:'. More forms may be added in the future to extend the capabilities.
Before comparing a URI with contents of this container, the following steps
MUST be performed:
-
Prior to verification, remove the signed JWT from the URI. This removal is only for the purpose of determining if the URI matches; all other purposes will use the original URI. If the signed JWT is terminated by anything other than a sub-delimiter (as defined in Section 2.2 of RFC 3986), everything from the reserved character (as defined in Section 2.2 of RFC 3986) that precedes the URI Signing Package Attribute to the last character of the signed JWT will be removed, inclusive. Otherwise, everything from the first character of the URI Signing Package Attribute to the sub-delimiter that terminates the signed JWT will be removed, inclusive.
-
Normalize the URI according to Section 2.7.3 of RFC 7230 and Sections 6.2.2 and 6.2.3 of [RFC 3986]. This applies to both generation and verification of the signed JWT.
Prefixed with 'hash:', this string is a URL Segment form (
Section 5 of
RFC 6920) of the URI.
Prefixed with 'regex:', this string is any regular expression compatible with POSIX (Section 9 of [
POSIX.1]) Extended Regular Expression used to match against the requested URI. These regular expressions
MUST be evaluated in the POSIX locale (Section 7.2 of [
POSIX.1]).
Note: Because '\' has special meaning in JSON [
RFC 8259] as the escape character within JSON strings, the regular expression character '\'
MUST be escaped as '\\'.
An example of a 'regex:' is the following:
[^:]*\\://[^/]*/dir/content/quality_[^/]*/segment.{3}\\.mp4(\\?.*)?
Note: Due to computational complexity of executing arbitrary regular expressions, it is
RECOMMENDED to only execute after verifying the JWT to ensure its authenticity.
The header of the JWT
MAY be passed via the CDNI Metadata interface instead of being included in the URISigningPackage. The header value
MUST be transmitted in the serialized encoded form and prepended to the JWT payload and signature passed in the URISigningPackage prior to verification. This reduces the size of the signed JWT token.