skip to content

In Amazon CloudFront, when would you protect private content with signed URLs versus signed cookies, and what does a trusted key group have to do with either?

level: middleimportance: must knowfreq 62%

answer

  1. one file versus a whole session
  2. the URL changes, or it does not
  3. public key lives in a key group
  4. cookies need your own domain name
  5. canned expiry versus custom policy conditions

basics

~20 s

CloudFront signed URLs authorize one object each and change the URL; signed cookies authorize many objects and leave URLs unchanged. Both are verified by CloudFront against the public keys in the trusted key group attached to that cache behavior.

solid answer

~50 s

Both mechanisms are the same primitive with a different delivery channel. You generate an RSA key pair, upload the public half to CloudFront as a public key inside a **key group**, and reference that key group as the trusted key group on a cache behavior — that is what turns on "restrict viewer access" for the paths that behavior matches. Your application holds the private key and signs. A **signed URL** carries `Signature`, `Key-Pair-Id` and either `Expires` (canned policy) or `Policy` (custom policy) as query parameters, and authorizes exactly one resource, so it suits a download link or a non-browser client. **Signed cookies** put the same values into `CloudFront-Signature`, `CloudFront-Key-Pair-Id` and `CloudFront-Policy`/`CloudFront-Expires`, so one authorization step covers every object under a wildcard — the right fit for a player pulling a manifest plus thousands of segments, since the URLs stay ordinary. Cookies require an alternate domain name you own, because you cannot set cookies on the `cloudfront.net` domain.

go deeper

for a junior

Know that CloudFront can serve private content only to requests carrying a valid signature, and that a signed URL protects one file while signed cookies cover many. Be able to name the query parameters or cookie names without hesitating.

for a middle

Explain the key-group model end to end: you generate the RSA pair, CloudFront stores only the public key, your service signs, and the cache behavior names the trusted key group. Contrast canned and custom policies and say which conditions each supports.

for a senior

Show the operational judgment: expiry lengths, non-disruptive key rotation using multiple keys in one group, private-key custody, and the fact that signing is worthless if the origin is reachable around CloudFront. Be ready to debug a 403 caused by clock skew or a mismatched key ID.

for a principal

Own the tradeoff between a bearer credential issued at the edge and a per-request authorization call. Be able to argue when the loss of revocation and audit granularity is acceptable in exchange for CDN offload, and to set the policy for key custody and rotation cadence across teams.

## What "restrict viewer access" actually turns on By default CloudFront serves an object to anyone who knows the URL. Enabling *restrict viewer access* on a **cache behavior** changes that: from then on CloudFront serves a request only if it carries a valid signature produced by a private key whose matching public key you have handed to CloudFront. It is a per-cache-behavior switch, not a per-distribution one, so the normal shape is a single distribution where the behavior matching `/assets/*` is open and the behavior matching `/media/*` is signed. ## Key groups: who holds what You generate an RSA key pair yourself. The public half is uploaded to CloudFront as a *public key* and placed in a *key group*; the cache behavior lists that key group as a trusted key group. CloudFront never holds the private key — your application does, usually pulled from Secrets Manager or Parameter Store at startup — and uses it to sign. The older mechanism, *trusted signers*, required CloudFront key pairs created by the account's root user; it still exists but key groups are the current answer and the one to describe in an interview. A key group can hold several public keys at once, which is precisely what makes key rotation non-disruptive: add the new public key, start signing with the new private key, and drop the old public key only after every credential signed with it has expired. ## Anatomy of a signed URL A signed URL is the ordinary object URL with signing parameters appended. With a **canned policy** you get three: `Expires`, `Signature`, `Key-Pair-Id`. A canned policy can express only one thing — an expiry on one exact resource. With a **custom policy** the expiry is replaced by a base64url-encoded `Policy` document, and that document can additionally express a start time (`DateGreaterThan`), a source IP or CIDR (`IpAddress`), and a wildcard `Resource` covering many paths. Custom policies produce longer URLs; that is the price of the extra conditions. ## Anatomy of signed cookies Signed cookies carry the same material under cookie names: `CloudFront-Signature`, `CloudFront-Key-Pair-Id`, and either `CloudFront-Expires` (canned) or `CloudFront-Policy` (custom). Your login or entitlement endpoint sets them with `Set-Cookie` after checking the user's subscription; the browser then attaches them to every subsequent request to that domain automatically. Because cookies are scoped to a domain, the distribution has to be reached through an alternate domain name that you control and that is covered by the cookie's `Domain` attribute — you cannot set cookies for `cloudfront.net`. This is the mechanism's one hard prerequisite and a common stumbling block. ## Choosing between them Reach for a **signed URL** when the grant is for one file, when the client is not a browser and will not keep a cookie jar, when you want to email or embed a time-limited link, or when different objects need genuinely different expiries. Reach for **signed cookies** when a session needs access to many objects, when you do not want to rewrite the URLs inside a manifest or an HTML page, and when the same object URL should be shareable across all entitled viewers so the CDN cache stays effective. Mixing the two on one request is not the intent: if a request carries both, CloudFront uses the signed URL. ## What signing does not do A signed URL or cookie is a bearer credential with an expiry. Whoever holds it can use it, and there is no per-credential revocation — your levers are short expiries, `IpAddress` in a custom policy, and rotating the key group. Clock skew matters, since expiry is absolute time. Signing also protects only the CloudFront path: if the origin bucket or server is reachable directly by another route, the signature is decoration. And a CloudFront signed URL is not an S3 presigned URL — the latter is a SigV4 signature made with IAM credentials and validated by S3 itself, while a CloudFront signature is RSA, made with your own private key, and validated at the edge. ```javascript // signature parameters, canned policy // https://cdn.example.com/media/a.mp4?Expires=1767225600&Signature=...&Key-Pair-Id=KEXAMPLE123456 ```

  • How would you rotate the RSA key pair behind your signed URLs without breaking credentials that are already in flight?
    Add the new public key to the same key group first, so CloudFront will accept signatures from either key. Switch your signing service to the new private key. Only after the longest credential lifetime has elapsed do you remove the old public key from the group. Because a key group holds multiple keys, the overlap window costs nothing.
  • What can a custom policy express that a canned policy cannot, and what does it cost you?
    A custom policy adds a start time, an IP address or CIDR restriction, and a wildcard resource so one signature covers many paths. The cost is URL length — the whole policy document is base64url-encoded into the URL — plus the operational trap that IP pinning breaks mobile clients that roam between networks.
  • Why can signed cookies not be used with the distribution's default cloudfront.net domain name?
    Cookies are scoped by domain, and you cannot set a cookie for a domain you do not control. Your entitlement endpoint has to set the CloudFront cookies for a domain that also resolves to the distribution, which means configuring an alternate domain name plus a matching certificate. Signed URLs have no such requirement.

saying these in an interview costs you the question

  • Thinks CloudFront signed URLs are the same as S3 presigned URLs
  • Says CloudFront signs the URL for you using a stored private key
  • Believes signing can be revoked for an individual URL or cookie
  • Assumes restrict viewer access applies to the whole distribution
  • Forgets signed cookies need an alternate domain name

context