Skip to content

How to use Edge Content Protection

Edge Content Protection (ECP) runs at Arc’s edge nodes and appends a variant query parameter to incoming request URLs before they are served by the CDN or PageBuilder. The variant is determined by validating a JWT cookie you provide and evaluating a priority-ordered rules document.

Request Flow

  1. Request arrives at the edge

    ECP intercepts the incoming request.

  2. Path check

    If include-paths or exclude-paths patterns are configured, ECP checks the request path against them before any cookie or JWT processing:

    • If an include-paths pattern is configured, requests that do not match are forwarded without a variant parameter and no further processing occurs.
    • If an exclude-paths pattern matches, the request is forwarded without a variant parameter and no further processing occurs.

    Patterns are ;-separated and support * and ? wildcards. See Configuration Parameters for details.

  3. Cookie lookup

    ECP looks for the cookie configured in the Delivery admin UI. If the cookie is absent, the request is forwarded to the CDN/PageBuilder without a variant parameter and the default PageBuilder template is used.

  4. JWT validation

    The cookie value is parsed as a signed JWT. The following checks are performed:

    CheckRule
    AlgorithmMust be HS256 or HS512
    exp claimMust be present and in the future
    SignatureVerified using the HMAC secret configured in the Delivery admin UI
    entitlements claimMust be present; absence renders the JWT invalid

    If validation fails, see Invalid JWT Handling.

  5. Rules evaluation

    The rules engine evaluates each rule in the uploaded rules document in priority order. A rule matches when both of the following are true:

    • The uri-pattern regular expression matches the incoming request URL.
    • The entitlements-pattern regular expression matches the entitlements claim value from the JWT.

    Processing stops at the first matching rule.

  6. Variant construction

    The variant query parameter value is assembled as:

    variant = <prepend claim value> + <resolver-query-param from matching rule>

    The prepend JWT claim is optional. If absent, only the resolver-query-param value is used. ECP appends ?variant=<value> to the request URL.

  7. Request forwarded

    The modified URL is passed to the CDN and PageBuilder for rendering. PageBuilder resolvers read the variant parameter and render the appropriate template.

    If no rule matches, the request is forwarded without a variant parameter and the default template is rendered.

Invalid JWT Handling

When JWT validation fails (bad signature, expired exp, missing entitlements claim), one of two behaviors applies:

  • Redirect URL configured: the browser is redirected to your system to obtain a new cookie, then back to the original page. See Cookie Lifecycle for the full refresh flow.
  • No redirect URL configured: the request is forwarded to the CDN/PageBuilder without a variant parameter, and the default template is rendered.

JWT Format

You generate and set the JWT cookie in your own external system. The JWT must be signed with HS256 or HS512 using the secret configured in the Delivery admin UI.

ClaimRequiredDescription
expYesExpiration timestamp (Unix epoch). Validated by ECP.
entitlementsYesComma-separated list of entitlement strings.
prependNoString prepended to the resolver-query-param value when constructing the variant.

Sample JWT Payload

{
"entitlements": "subscriber,tier_gold",
"prepend": "us_",
"exp": 1763035200
}

With this payload, suppose a rule whose entitlements-pattern matches "subscriber,tier_gold" has "resolver-query-param": "premium". The resulting query parameter is ?variant=us_premium. The entitlements value is used only for pattern matching — it is the rule’s resolver-query-param that determines the variant.

You set and refresh the JWT cookie; Arc does not issue, modify, or renew it. You control when and how the cookie is written — typically after a user signs in or completes a subscription purchase in your own system.

Expiration and Refresh

The exp claim in the JWT determines how long the cookie remains valid before ECP rejects it. You choose this value, and the choice involves a trade-off:

exp strategyEffect
Long expirationCookie is refreshed infrequently. Entitlements in the JWT may become stale — for example, a subscriber who cancels may continue to receive premium content until the cookie expires.
Short expirationCookie is refreshed frequently, keeping entitlements current. However, each expiry triggers a redirect cycle: Arc redirects the user to your system to obtain a new cookie, then back to the original page. Frequent redirects degrade the user experience.

Choose an expiration window that balances entitlement accuracy against the disruption of redirect-based refreshes.

Refresh Flow

When a JWT expires or is otherwise invalid and a redirect URL is configured, the following flow occurs:

  1. The user’s request arrives at the edge with an expired cookie.
  2. ECP rejects the JWT and redirects the browser to your configured redirect URL.
  3. Your system authenticates the user, issues a new JWT, and sets a fresh cookie.
  4. Your system redirects the browser back to the original page.
  5. ECP validates the new cookie and applies the appropriate variant.

If no redirect URL is configured, expired cookies are silently treated as absent — the user receives the default template with no redirect.

Rules Document

The rules document is a JSON file uploaded in the Delivery admin UI. It contains a prioritized list of matchers. Rules are evaluated in ascending priority order; the first rule that matches both the request URL and the entitlements claim is used.

Regular Expression Engine

Both uri-pattern and entitlements-pattern are evaluated using the RE2 regular expression engine. RE2 is designed for high-throughput matching at the edge and guarantees linear-time execution regardless of input size. The trade-off is that RE2 does not support certain features available in other engines — notably backreferences and lookahead/lookbehind assertions.

The patterns are used for matching, not parsing. Capture groups are accepted in the syntax but their captured values are not used; only whether the overall pattern matches determines rule evaluation.

Rule Fields

FieldTypeDescription
priorityintegerEvaluation order. Lower numbers are evaluated first.
uri-patternstringRE2 regular expression tested against the incoming request URL. The rule matches if the pattern matches anywhere in the URL unless anchored with ^ and $.
entitlements-patternstringRE2 regular expression tested against the full entitlements claim string. The rule matches if the pattern matches anywhere in the value.
resolver-query-paramstringThe value used as (or appended to the prepend value to form) the variant query parameter.

Sample Rules Document

{
"matchers": [
{
"priority": 1,
"uri-pattern": "^(\\/sports\\/.*\\/[0-9]{4}\\/[0-9]{2}\\/[0-9]{2}\\/.*)$",
"entitlements-pattern": "\\b(sports_ads)\\b",
"resolver-query-param": "sports_ads"
},
{
"priority": 2,
"uri-pattern": "^(\\/sports\\/.*\\/[0-9]{4}\\/[0-9]{2}\\/[0-9]{2}\\/.*)$",
"entitlements-pattern": "\\b(sports_no_ads|premium)\\b",
"resolver-query-param": "sports_no_ads"
},
{
"priority": 3,
"uri-pattern": "^(\\/.*)$",
"entitlements-pattern": "\\b(premium)\\b",
"resolver-query-param": "premium"
}
]
}

In this example:

  • A reader with entitlements: "sports_ads" visiting a sports article URL matches rule 1 and receives ?variant=sports_ads.
  • A reader with entitlements: "sports_no_ads,premium" visiting the same URL matches rule 2 (rule 1 does not match their entitlements) and receives ?variant=sports_no_ads.
  • A reader with entitlements: "premium" visiting a non-sports URL skips rules 1 and 2 (URI pattern does not match) and matches rule 3, receiving ?variant=premium.
  • A reader with no matching entitlements receives no variant parameter and sees the default template.

Configuration Parameters

These are configured in the Delivery admin UI under Site settings → Edge Integrations → Content Protection.

ParameterRequiredDescription
Cookie nameYesName of the cookie that contains the JWT. Must match what your external system sets.
HMAC secretYesSecret used to validate the JWT signature. Must match the secret used to sign the cookie.
Rules documentYesJSON file containing the prioritized list of matchers (see Rules Document).
Include pathsNo;-separated wildcard patterns (*, ?). If set, only requests whose path matches at least one pattern are processed by ECP; all others are forwarded as-is.
Exclude pathsNo;-separated wildcard patterns (*, ?). Requests whose path matches any pattern bypass ECP processing entirely.
Redirect URLNoURL to redirect users to when JWT validation fails. If not set, requests without a valid JWT are forwarded without a variant parameter.

PageBuilder Integration

ECP works with PageBuilder resolvers. Each unique variant value must correspond to a PageBuilder template configured to handle it.

For more information, see Configuring resolvers.

Cost Considerations

Cache Clearing Compatibility

Migrating from Arc’s Server-Side Paywall

ECP is the successor to Arc's Server-Side Paywall (SSP). If you already run SSP, you can move to ECP gradually, with no cutover downtime, because both features run at the edge and SSP is evaluated before ECP. For a conceptual comparison of the two, see What is Edge Content Protection?.

How the Two Features Coexist

Arc’s edge logic evaluates SSP first and ECP second, and both can be enabled at the same time. To let them run cleanly side by side during migration, give ECP a different cookie name than your SSP cookie. With distinct names, each reader is handled by whichever cookie is present on their request:

  • A reader who still carries the SSP cookie (entitlement.timestamp.hash) is handled by SSP, exactly as before. ECP finds no JWT cookie and passes the request through untouched.
  • A reader who has been issued the new ECP JWT cookie is passed through by SSP (which finds no SSP cookie) and handled by ECP.

Using the same name for both would force SSP to attempt to parse the JWT as an entitlement.timestamp.hash value and vice versa, so keep them separate until SSP is fully retired.

Because the two run side by side, you can migrate readers in place — as cookies are reissued, traffic shifts from SSP to ECP with no coordinated cutover.

Migrate in two phases so that no PageBuilder work is required up front.

Phase 1 — Switch the cookie format, keep everything else the same.

Keep your existing PageBuilder templates and resolvers untouched and change only the cookie your middleware issues:

  1. Update your middleware to set an ECP JWT under a new, dedicated cookie name (distinct from your SSP cookie) instead of the SSP entitlement.timestamp.hash cookie. This is not a value-format tweak — you must emit a real signed JWT (see JWT Format), not an HMAC over a dotted string. Keeping the SSP cookie name reserved for SSP lets both features run without interfering with each other during the rollout.
  2. Configure an ECP rules document whose resolver-query-param values reproduce the variant values your current resolvers already expect (for SSP these are 1 and 2), with no prepend. ECP then produces the same ?variant=1 / ?variant=2 URLs SSP produced, so your existing templates render unchanged.
  3. Roll the middleware change out. As readers’ cookies are reissued on their next sign-in or revalidation, they move from SSP handling to ECP handling transparently.

Phase 2 — Adopt ECP’s new capabilities.

Once effectively all readers carry an ECP JWT, begin taking advantage of what ECP adds over SSP:

  • Expand the entitlements claim from two buckets to any number of arbitrary strings.
  • Add per-URL uri-pattern rules, priority ordering, and include/exclude paths instead of a single site-wide rule.
  • Introduce new variant values (and matching PageBuilder templates), optionally using prepend, for additional reader experiences.

Retire SSP once no meaningful traffic still depends on it.

Concept Mapping

SSPECP
Cookie value entitlement.timestamp.hashSigned JWT (HS256 or HS512) with entitlements, exp, and optional prepend claims
Entitlement is the integer 1 or 2entitlements is a comma-separated list of arbitrary strings
HMAC-SHA256 over entitlement.timestamp, signed with a TAM-provided shared secretStandard JWT signature verified with the HMAC secret configured in the Delivery admin UI
Cookie name and shared secret assigned by your Technical Account ManagerCookie name, HMAC secret, and rules document configured by you in the Delivery admin UI
Two entitlement buckets, applied site-wideUnlimited entitlements, matched per-URL by a priority-ordered rules document
variant = the entitlement integer, or absent when no cookie is presentvariant = prepend + the matching rule’s resolver-query-param
Revalidation timestamp embedded in the cookie (must be < 90 days out)exp claim (Unix epoch)
Expired cookie → CDN 302 to your returnUrl login/revalidation endpointInvalid or expired JWT → redirect to the configured Redirect URL, following the same refresh flow

Migration Checklist

  1. Provision ECP. Submit a ticket through the Arc XP Customer Support (ACS) portal to enable ECP for your organization.
  2. Inventory your SSP setup. Record the current cookie name and shared secret, your two entitlement buckets and the resolver/template each maps to, your middleware endpoints, and your login/revalidation (returnUrl) endpoint.
  3. Configure ECP to mirror SSP. In the Delivery admin UI, set a new ECP cookie name (distinct from your SSP cookie), the HMAC secret, and the Redirect URL, and upload a rules document whose resolver-query-param values match the variant values your existing resolvers already handle.
  4. Update middleware to issue a JWT. Emit a JWT containing entitlements and exp (and prepend only if you need it), signed with the ECP HMAC secret, under the new ECP cookie name — leaving the SSP cookie name untouched so SSP continues to serve readers who have not yet migrated.
  5. Verify parity. In a test environment, confirm that each reader bucket produces the same variant — and therefore the same rendered template — under ECP as it did under SSP.
  6. Roll out and let cookies age over. Deploy the middleware change; readers migrate from SSP to ECP as their cookies are reissued.
  7. Evolve, then decommission. After the migration window, expand your rules and templates to use ECP’s richer capabilities, then retire SSP.

Security and Best Practices

  • Use a strong HMAC secret (minimum 32 characters recommended) to prevent JWT forgery.
  • Set short exp values in JWTs and rotate secrets periodically.
  • Design entitlements-pattern expressions to be as specific as possible to avoid unintended rule matches.
  • Keep the number of unique variant values low to control PageBuilder rendering costs.
  • Use the redirect URL to direct users with invalid or expired JWTs to a sign-in or upgrade page.
  • Ensure your redirect endpoint always issues a valid, correctly signed JWT before redirecting back to Arc. A redirect endpoint that repeatedly produces an invalid cookie triggers Arc’s WAF loop protection, blocking the affected browser until the WAF block expires — Arc has no way to clear this block; it expires on its own.