Signed URL Verification
The Edge Function verifies signed URLs to gate access to protected content. Two verification modes are available, chosen per deployment: CDN-native verification and custom HMAC verification.
Verification Modes
Section titled “Verification Modes”Mode A: CDN-Native Verification (CloudFront, Akamai)
Section titled “Mode A: CDN-Native Verification (CloudFront, Akamai)”The CDN platform handles signature verification at the infrastructure level, before the edge function code runs.
CloudFront implementation: Configure a trusted_key_groups reference on the cache behavior for /premium/*. Upload the RSA public key to CloudFront Key Management. CloudFront verifies the Signature, Key-Pair-Id, and Expires (or canned/custom Policy) parameters before the request reaches any function code.
Akamai implementation: Configure EdgeAuth token verification on the property manager for protected paths. The EdgeAuth token includes a hash, expiry, and optional IP binding. Verification happens at the property level.
The Edge Function does not verify the cryptographic signature in this mode. It only performs additional checks (agent binding, single-use) that the CDN cannot do natively.
Mode B: Custom HMAC Verification (Cloudflare, Fastly)
Section titled “Mode B: Custom HMAC Verification (Cloudflare, Fastly)”The edge function code verifies the signature using HMAC-SHA256.
URL Parameter Parsing
Section titled “URL Parameter Parsing”HMAC signed URL format (current implementation):
https://cdn.provider.com/premium/article.html?expires=1773451434&sig=a7f3b2c1...expires— Unix timestamp (seconds since epoch).sig— HMAC-SHA256 hex digest of{baseURL}{expires}using the shared secret.
Production enhancement — add delimiter and agent binding:
https://cdn.provider.com/premium/article.html ?expires=1773451434 &agent_id=sha256(LIC-BUYER-001) &txn_id=txn-mp-93a7f2 &sig=HMAC-SHA256(baseURL\nexpires\nagent_id\ntxn_id, secret)agent_id— SHA-256 hash of the agent’s license ID. The URL parameteragent_idcarries the value from proto’sTransactionResponse.agent_identity_hashfield (SHA-256 of the agent’s license ID).txn_id— transaction ID for reconciliation and single-use enforcement.\ndelimiter between fields prevents canonicalization ambiguity (as noted in the threat model’s HMAC implementation note).
HMAC Canonicalization
Section titled “HMAC Canonicalization”Both the Exchange (signer) and the edge function (verifier) MUST use the same canonical format for HMAC input. Fields are concatenated with \n delimiters in this fixed order:
baseURL\nexpires\nagent_id\ntxn_idWhere:
baseURL— the content URL without query parameters (e.g.,https://cdn.example.com/premium/article.html)expires— Unix timestamp in seconds (string representation)agent_id— SHA-256 hex hash of the agent’s license ID (matchesTransactionResponse.agent_identity_hash)txn_id— the transaction ID (ULID)
All four fields are REQUIRED in production signed URLs. The agent_id field binds the URL to a specific agent (preventing sharing, Threat T8). The txn_id field enables three-sided reconciliation (CDN logs, Exchange transactions, Usage reports).
This canonicalization format MUST match the Exchange’s signing format. Any mismatch between signer and verifier will cause all signed URLs to be rejected.
TTL Checking
Section titled “TTL Checking”Signed URLs include an expiry timestamp. The edge function enforces two checks:
- Expiry check — reject URLs where
expires< current time. - Max TTL check — reject URLs where
expiresis more thanmaxUrlTtlSecondsfrom the current time (prevents URLs signed too far in the future).
The default max TTL is 300 seconds (5 minutes). This limits the replay window even without single-use enforcement.
Timing-Safe Comparison
Section titled “Timing-Safe Comparison”HMAC comparisons use constant-time comparison (XOR loop), never ===. This prevents timing side-channel attacks where an attacker could determine partial signature matches based on response timing.
| Operation | Time |
|---|---|
| HMAC-SHA256 computation (Web Crypto) | 0.1-0.5ms |
| Timing-safe comparison (64-byte hex) | < 0.01ms |
Agent Identity Binding
Section titled “Agent Identity Binding”When agentBindingEnabled is true, the edge function validates that the requester matches the agent_id bound into the signed URL.
End-to-end agent identity flow:
- Agent calls
ExecuteTransactionwithaisystem.aisysuse.lid(license ID, e.g.,LIC-BUYER-001). - Exchange computes
agent_id_hash = SHA256(license_id). - Exchange embeds
agent_id_hashin the signed URL:?Signature=...&agent_id=abc123... - Agent fetches the signed URL with header:
X-Agent-License-Id: LIC-BUYER-001 - Edge function extracts
agent_idfrom URL parameter, extractslicense_idfromX-Agent-License-Idheader, computesSHA256(header_value), compares against URL parameter.- Match: serve content.
- Mismatch: 403.
The agent does not need to know the hash — it just sends its license_id in a header. The Exchange and the edge function independently compute the same hash.
Identity verification methods:
| Method | Reliability | Notes |
|---|---|---|
X-Agent-License-Id request header | Medium | Agent self-reports. Can be spoofed. |
TLS client certificate CN or SAN | High | Requires mTLS setup. Not common yet. |
OAuth2 access_token introspection | High | Requires network call. Expensive at edge. |
| IP address hash | Low | Multi-tenant IPs, NAT, proxies. |
Recommended approach for v1: X-Agent-License-Id header with SHA-256 hash comparison against the agent_id URL parameter. This prevents casual URL sharing but does not prevent a determined attacker who knows the license ID.
Future: mTLS with agent certificates issued by a RAMP-recognized CA.
Single-Use URL Enforcement
Section titled “Single-Use URL Enforcement”For providers wanting additional replay protection, the edge function can enforce single-use URLs via edge KV:
KV TTL: Set to maxUrlTtlSeconds + 60s (URL max TTL plus a safety buffer). After this period, the signed URL is expired anyway, so the KV entry can be evicted.
Single-use enforcement is best-effort. CDN edge KV stores are eventually consistent across locations. The primary replay protection is agent identity binding + short TTL (5 minutes). Authoritative deduplication happens during reconciliation via CDN access logs and Exchange transaction records.
CDN KV consistency reality:
| Platform | KV Mechanism | Consistency Model | Propagation Delay |
|---|---|---|---|
| CloudFront | No native KV; Lambda@Edge + DynamoDB | Per-region, eventually consistent (DynamoDB Global Tables) | Seconds across regions |
| Cloudflare Workers KV | Workers KV | Eventually consistent | ~60s propagation across PoPs |
| Cloudflare Durable Objects | Durable Objects | Strong consistency | Single-location (latency tradeoff) |
| Akamai EdgeKV | EdgeKV | Eventually consistent | ~5-10s in-region |
| Fastly KV Store | KV Store | Eventually consistent | Seconds across PoPs |
Recommendation: Do not enforce strict single-use at the edge. Instead, use:
- Agent identity binding — the signed URL is bound to a specific agent_id. Even if replayed, only the authorized agent can use it.
- Short TTL (5 minutes) — limits the replay window to a narrow period.
- Reconciliation (detect abuse after the fact) — the Exchange transaction log and CDN access logs contain
txn_idfor every request. Cross-reference to detect replays and take action.
This matches ad-tech’s approach to impression deduplication: real-time is best-effort, reconciliation is authoritative.
Key Custody Model
Section titled “Key Custody Model”The edge function verifies, it does not sign.
| Signing Scheme | Who Signs | Who Verifies | Edge Function Has |
|---|---|---|---|
| CloudFront RSA (asymmetric) | Exchange (private key) | CloudFront infra (public key) | Nothing (CDN-native) |
| Akamai EdgeAuth (symmetric) | Exchange (shared secret) | Akamai infra (shared secret) | Nothing (CDN-native) |
| HMAC-SHA256 (symmetric) | Exchange (shared secret) | Edge function (same secret) | The shared secret |
| RSA/Ed25519 (asymmetric, custom) | Exchange (private key) | Edge function (public key) | Public key only |
Concern with HMAC: When using HMAC verification (Cloudflare, Fastly), the edge function must hold the shared secret. If the edge function is compromised, the attacker can forge signed URLs. Key rotation requires updating both the Exchange and the edge function simultaneously.
Recommendation: Use asymmetric signing (Ed25519 or RSA) when the CDN does not provide native signed URL verification.