Skip to content

Cloudflare Zero Trust

We've got built-in support for Cloudflare Zero Trust authentication. It's the easiest to setup and is fully managed with Terraform; all you need to do is create and OAuth app (using a provider of your choice), add it to Cloudflare, and then set the AUTH_MODE=cloudflare env var.

1. Create Cloudflare Access Application

  1. Go to Cloudflare Zero Trust Dashboard
  2. Navigate to Access → Applications, and click Add an application → Self-hosted
  3. Configure your application, with a name, session duration, and your domain

2. Configure an Identity Provider

In this example, we'll use GitHub, but you can choose any supported identify provider

  1. Log into GitHub, go to Settings → Developer settings → OAuth Apps
  2. Create a new app, give it a name, and then set:
    • Homepage URL: https://YOUR_TEAM.cloudflareaccess.com
    • Authorization callback URL: https://YOUR_TEAM.cloudflareaccess.com/cdn-cgi/access/callback
  3. Create a new Client ID and Client Secret from your GitHub app, and make note of it

Then

  1. Head back to your Zero Trust Dashboard, go to Settings → Authentication
  2. Click Add new under Login methods, and choose your provider (like GitHub)
  3. Paste in your Client ID and Client Secret, and save

3. Add Access Policy

This is where you specify who will be able to access your app. It could be everyone, just users from a specific domain, specific IP addresses, or just you.

  1. In your Access application, go to Policies tab
  2. Click Add a policy
  3. Configure policy, with a name, an action (like include) and then choose your criteria
  4. And save the policy

4. Add the Variables

Finally, you need to tell Pixelflare to use Cloudflare Access for authentication. Add this to your env vars:

bash
AUTH_MODE=cloudflare

How It Works

Once Cloudflare Access is configured:

  • User visits your Pixelflare application
  • Cloudflare Access intercepts the request and validates authentication
  • User logs in with GitHub (or configured identity provider) if not already authenticated
  • Cloudflare Access issues a JWT token in the Cf-Access-Jwt-Assertion header
  • Pixelflare API verifies the JWT signature using Cloudflare's public certs
  • User identity is extracted from JWT claims and a unique owner ID is generated
  • All subsequent requests are automatically authenticated via the JWT token

Flow

mermaid
sequenceDiagram
    participant U as User Browser
    participant CF as Cloudflare Access (Zero Trust)
    participant IdP as Identity Provider (IdP)
    participant APP as Origin App / Service

    %% 1. Initial request
    U->>CF: HTTPS request to protected app URL
    CF->>CF: Check Access policy for requested app

    alt Has valid CF Access token cookie
        CF->>CF: Validate token (signature, expiry, policy)
        alt Token valid and allowed
            CF->>APP: Forward HTTP request with CF-Access-* headers
            APP-->>CF: HTTP response
            CF-->>U: Response to user
        else Token invalid/expired
            CF->>U: Redirect to IdP / Access login
        end
    else No Access token
        CF->>U: Redirect to IdP / Access login
    end

    %% 2. Authentication with IdP
    U->>IdP: OpenID Connect / SAML auth request (via redirect)
    IdP->>U: Login form (username/password, MFA, etc.)
    U->>IdP: Submit credentials + MFA
    IdP->>IdP: Authenticate user & build identity claims
    IdP-->>U: Redirect with auth code / assertion

    %% 3. Cloudflare validates and issues Access token
    U->>CF: Send auth code/assertion to callback URL
    CF->>IdP: Back-channel token/metadata validation
    IdP-->>CF: Token introspection / user claims
    CF->>CF: Evaluate Access policies (groups, emails, device posture)
    alt Policy allows access
        CF->>U: Set CF_Authorization / CF-Access-Token cookie (JWT)
        CF->>APP: Forward original HTTP request with identity headers
        APP-->>CF: HTTP response
        CF-->>U: Response to user
    else Policy denies access
        CF-->>U: Access denied (403 / policy error page)
    end

    %% 4. Subsequent requests
    loop Subsequent requests until token expiry
        U->>CF: HTTP request with CF-Access cookie
        CF->>CF: Validate token & policy
        CF->>APP: Forward request with CF-Access-* headers
        APP-->>CF: HTTP response
        CF-->>U: Response
    end

JWT Verification

  • JWT in Cf-Access-Jwt-Assertion header or CF_Authorization cookie
  • Fetches verification certs from CF_ACCESS_CERTS_URL
  • Verifies signature using RS256 algorithm
  • Validates audience claim matches CF_ACCESS_AUD
  • Validates expiration and not-before claims
  • Caches certs for 60 minutes

Released under the MIT License.