Cloudflare Access Configuration

8 min read Intermediate

Cloudflare Access replaces VPNs with identity-aware application access. Every request is authenticated and authorized at the edge before reaching your application. This guide covers standard configuration patterns.

Core Concepts

Cloudflare Access evaluates identity on every request. Key differences from VPN:

  • VPN grants network-level access. A compromised credential exposes the entire network.
  • Access grants application-level access. Each application has its own policy. Blast radius is limited to one app.

Access works by injecting an authentication step at the Cloudflare edge. Users authenticate via your identity provider, and Cloudflare issues a signed JWT. Your application can optionally validate this JWT for defense in depth.

IdP Integration

Access supports multiple identity providers simultaneously. Common configurations:

  • Azure AD / Entra ID - enterprise SSO, group-based policies
  • Google Workspace - domain-based access
  • Okta - enterprise SSO with MFA
  • GitHub - useful for developer tools and staging environments
  • One-Time PIN (OTP) - email-based access for external users without IdP accounts
Multiple IdPs: You can configure multiple identity providers for the same Access application. This is useful when internal staff use Azure AD but external contractors use OTP.

Application Setup

Each protected application is defined by:

  • Application domain - the hostname to protect (e.g., app.example.com)
  • Application type - Self-hosted, SaaS, or Bookmark
  • Session duration - how long the JWT is valid before re-authentication

Create an application via API

curl -X POST "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/access/apps" \
  -H "Authorization: Bearer ${API_TOKEN}" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "Internal Dashboard",
    "domain": "dashboard.example.com",
    "type": "self_hosted",
    "session_duration": "12h",
    "auto_redirect_to_identity": true
  }'

Access Policies

Policies define who can access the application. Each application can have multiple policies evaluated in order.

Policy types

  • Allow - grant access if conditions match
  • Block - deny access if conditions match
  • Bypass - skip authentication (use with extreme caution)
  • Service Auth - for machine-to-machine access via service tokens

Common policy patterns

# Allow engineering team (Azure AD group)
Include: Azure AD Groups = "Engineering"
Require: Country = "AT", "DE", "CH"

# Allow specific email domain
Include: Emails ending in = "@example.com"

# Block external access except via OTP
Include: Login Methods = "OTP"
Exclude: Country not in = "AT", "DE"

Service Tokens

Service tokens enable machine-to-machine authentication without user interaction. Use them for CI/CD pipelines, monitoring, and API integrations.

  • Each token is a client ID + client secret pair
  • Passed as HTTP headers: CF-Access-Client-Id and CF-Access-Client-Secret
  • Tokens have configurable expiry (rotate regularly)
  • Scope tokens to specific applications via Service Auth policies
# Authenticate with a service token
curl -H "CF-Access-Client-Id: ${CLIENT_ID}" \
     -H "CF-Access-Client-Secret: ${CLIENT_SECRET}" \
     https://api.example.com/health

Session Management

Session duration controls how often users must re-authenticate:

  • Short (1-4h) - high-security applications, admin panels
  • Medium (8-12h) - standard business applications (typical workday)
  • Long (24h-7d) - low-risk internal tools, documentation

Set the application-level session duration, not the IdP session. Access re-authenticates against the IdP when the Access session expires, regardless of whether the IdP session is still active.

Audit Logging

Access logs every authentication event. Logs include:

  • User email and identity provider
  • Application accessed
  • Policy matched (allow/deny)
  • Source IP and country
  • Timestamp
# Retrieve Access audit logs
curl -s "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/access/logs/access_requests?limit=25" \
  -H "Authorization: Bearer ${API_TOKEN}" \
  | jq '.result[] | .user_email, .action, .created_at, .ip_address'
Full Zero Trust deployment? See our Cloudflare Everywhere Security engagement for Access + Tunnel configuration with IdP integration, policy design, and evidence packs.