CloudFlare


Category: How-To Guide

Overview

In this guide, you’ll learn how to build a server-side paywall using Pelcro and Cloudflare Workers to securely enforce content access at the edge.

You’ll use Pelcro’s Authentication and Authorization APIs to:

  • Identify logged-in users from their Pelcro token.
  • Retrieve the user resource.
  • Verify the user’s entitlements before serving premium content.

By the end, you’ll have a working Cloudflare Worker that authenticates a Pelcro user, checks their subscription, and conditionally serves or blocks content.

Prerequisites

  • A Pelcro tenant with API access (server-side key).
  • A Cloudflare account with Workers and KV storage enabled.
  • A CMS that adds X-Access-Tier and X-Content-Id headers per page.

Step 1 — Understand the Flow

A server-side paywall runs before your content is served. Cloudflare Workers intercept the request, validate the user’s Pelcro token, and call Pelcro APIs to check entitlements.

User → Cloudflare Worker → Pelcro API (auth + entitlements) → CMS (content)

If the user is entitled, the Worker lets the request continue to your CMS. Otherwise, it blocks or shows a preview.

Step 2 — Authenticate the User via Pelcro

According to Pelcro’s Authenticate a Customer recipe, you can retrieve a user’s information using their token.

After login on your site, Pelcro sets a cookie like:

pelcro_session=<JWT_TOKEN>

Inside your Worker, extract the token and call the Pelcro Open API /user endpoint:

async function getUserFromPelcro(apiBase, token) {
  const res = await fetch(`${apiBase}/user`, {
    headers: {
      "Authorization": `Bearer ${token}`,
      "Content-Type": "application/json"
    }
  });
  if (!res.ok) return null;
  const data = await res.json();
  return data.data; // returns the Pelcro user resource
}

Response Example:

{
  "data": {
    "id": 12345,
    "email": "[email protected]",
    "subscriptions": [ { "plan_id": 6789, "status": "active" } ]
  }
}

Tip: Store your PELCRO_API_URL (e.g., https://www.pelcro.com/) as an environment variable or Worker Secret.

Step 3 — Check Entitlements

Following Pelcro’s Authorization recipe, you can verify whether the user has access to a specific resource (content, tier, or plan).

You’ll call the /authorization endpoint to check entitlement state:

async function checkEntitlement(apiBase, token, resourceType, resourceId) {
  const res = await fetch(`${apiBase}/authorization`, {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${token}`,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      data: {
        type: "authorization",
        attributes: {
          resource_type: resourceType,
          resource_id: resourceId
        }
      }
    })
  });

  const data = await res.json();
  return data.data.attributes.allowed; // true or false
}

Example Request:

{
  "data": {
    "type": "authorization",
    "attributes": {
      "resource_type": "content",
      "resource_id": "article-123"
    }
  }
}

Example Response:

{
  "data": {
    "type": "authorization",
    "id": "12345",
    "attributes": {
      "allowed": true
    }
  }
}

Step 4 — Combine Authentication and Authorization in the Worker

Here’s how the complete Cloudflare Worker ties everything together:

export default {
  async fetch(req, env) {
    const url = new URL(req.url);
    const cookies = parseCookies(req.headers.get("Cookie") || "");
    const token = cookies["pelcro_session"];
    const accessTier = req.headers.get("X-Access-Tier") || "standard";
    const contentId = req.headers.get("X-Content-Id") || url.pathname;

    // Step 1: Authenticate
    const user = await getUserFromPelcro(env.PELCRO_API_URL, token);

    // Step 2: Check entitlement
    const allowed = user
      ? await checkEntitlement(env.PELCRO_API_URL, token, "content", contentId)
      : false;

    // Step 3: Enforce paywall
    if (allowed || accessTier === "free") {
      return fetch(req);
    }

    // Not allowed — redirect to Pelcro offers
    return Response.redirect("https://yourdomain.com/subscribe", 302);
  }
};

function parseCookies(str) {
  return Object.fromEntries(str.split(";").map(v => v.trim().split("=")).filter(p => p[0]));
}

Note: This Worker enforces the paywall server-side, so users cannot bypass access control by disabling JavaScript.

Step 5 — Deploy

  1. Save your Worker code.
  2. Store PELCRO_API_URL as a secret:
    npx wrangler secret put PELCRO_API_URL
  3. Deploy your Worker:
    npx wrangler publish

Troubleshooting

ProblemCauseSolution
401 UnauthorizedToken expired or missingConfirm Pelcro cookie (pelcro_session) is present and valid
Content cached incorrectlyMissing cache variation by entitlementAdd Vary: X-Access-State header in Worker
Slow responsesEntitlement API not cachedUse Cloudflare KV to store entitlement results for a few minutes

Next Steps

Summary

You’ve successfully implemented a server-side paywall using Cloudflare Workers and Pelcro APIs. Your Worker now:

  • Authenticates users with their Pelcro session token.
  • Verifies entitlements for each content request.
  • Enforces paywall logic before the CMS responds.

This design keeps premium content secure, improves performance, and provides a scalable integration pattern for publishers using Zephyr or Naviga with Pelcro.