Client Area

Cloudflare Zero Trust and Access for Internal Apps

ByDomain India Team·DomainIndia Engineering
6 min readPublished 21 Apr 2026Updated 23 Jun 2026988 views

In this article

  • 1Why Zero Trust for internal apps
  • 2Architecture
  • 3Step 1 — Enable Cloudflare Zero Trust
  • 4Step 2 — Add SSO provider
  • 5Step 3 — Create an Access application

Cloudflare Zero Trust and Access for Internal Apps

TL;DR
Cloudflare Access puts a zero-trust gateway in front of your internal apps — admin panels, staging sites, internal dashboards. No VPN needed. Employees authenticate with Google Workspace / Microsoft 365 / OTP, and Cloudflare blocks everyone else at the edge. This guide covers the full setup for a DomainIndia-hosted app.

Why Zero Trust for internal apps

Traditional: admin panel at admin.yourcompany.com → protect with basic auth + IP whitelist.

Problems:

  • Basic auth passwords leak
  • IP whitelist breaks when staff work from cafes
  • No audit trail of who accessed what
  • VPN for everyone is heavy and brittle

Zero Trust:

  • Employees log in with SSO (Google, Microsoft, Okta)
  • Cloudflare verifies identity at the edge
  • Each app has its own policy (which users, from where, with MFA)
  • Every request logged
  • No passwords or shared secrets

Free plan: up to 50 users free. Paid: $3-7/user/month.

Architecture

Employee browser
    │
    ▼
Cloudflare edge ◄── SSO provider (Google/Microsoft/Okta)
    │
    ▼  (identity verified)
DomainIndia origin (admin app, staging, internal tool)

Cloudflare inserts an Authorization header or JWT; your origin trusts it because the traffic arrives via Cloudflare Tunnel.

Step 1 — Enable Cloudflare Zero Trust

  1. Log in to Cloudflare dashboard
  2. Zero Trust (in left sidebar) → click "Launch"
  3. Choose team name (becomes team-name.cloudflareaccess.com)
  4. Select "Free" plan (sufficient for most small teams)

Step 2 — Add SSO provider

Zero Trust → Settings → Authentication → Login methods → Add new.

Google Workspace:

  • Create OAuth 2.0 credentials in Google Cloud Console
  • Add redirect URI shown by Cloudflare
  • Copy Client ID + Secret into Cloudflare

One-time PIN (no SSO):

  • Simplest — users get emailed a code
  • Good for external contractors / partners

Step 3 — Create an Access application

Zero Trust → Access → Applications → Add application → Self-hosted.

  • Application name: Admin Panel
  • Subdomain: admin
  • Domain: yourcompany.com
  • Session duration: 24 hours

Policy:

  • Action: Allow
  • Include: Emails ending in @yourcompany.com
  • Require: Authentication via Google

Optional extra:

  • Require MFA (once Google provides it)
  • Include specific IPs (office network)
  • Require certain countries (block rest of world)

Traditional: expose your origin to the internet + use Access to block.

Better: Cloudflare Tunnel — origin makes outbound connection, never exposes a public port.

  1. Zero Trust → Networks → Tunnels → Create tunnel
  2. Name the tunnel
  3. Copy the install command shown, run on your DomainIndia VPS:

```bash

curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.rpm -o cloudflared.rpm

sudo rpm -i cloudflared.rpm

sudo cloudflared service install <TOKEN_FROM_DASHBOARD>

```

  1. Configure routes:

- Hostname: admin.yourcompany.com

- Service: http://localhost:3000 (your internal app)

  1. DNS auto-configures — no manual DNS record needed

Origin server (localhost:3000) never exposed to internet. Traffic exits only to Cloudflare.

Step 5 — Verify origin identity

Your app should only trust requests from Cloudflare Access. Two options:

Option A — `Cf-Access-Jwt-Assertion` header:

Cloudflare adds this JWT header to every authenticated request. Verify in your app:

javascript
import jwt from 'jsonwebtoken';
import jwksClient from 'jwks-rsa';

const client = jwksClient({
  jwksUri: 'https://team-name.cloudflareaccess.com/cdn-cgi/access/certs',
});

app.use(async (req, res, next) => {
  const token = req.headers['cf-access-jwt-assertion'];
  if (!token) return res.status(401).send('No access token');

  const decoded = jwt.decode(token, { complete: true });
  const key = await client.getSigningKey(decoded.header.kid);
  const payload = jwt.verify(token, key.getPublicKey(), {
    audience: 'YOUR_AUD',  // shown in Access app settings
    issuer: 'https://team-name.cloudflareaccess.com',
  });

  req.user = { email: payload.email, groups: payload.groups };
  next();
});

Option B — `CF-Connecting-IP` whitelist:

Only accept requests from Cloudflare IP ranges. Simpler but less strong. See Cloudflare IP list.

Step 6 — Policies for fine-grained access

Different rules for different apps:

Application: Production database console
  Policy: Allow
    Include: user is DBA role
    Require: MFA + India-only IP
  Session: 1 hour
Application: Marketing CMS
  Policy: Allow
    Include: @yourcompany.com OR [email protected]
  Session: 8 hours
Application: Staging site
  Policy: Allow
    Include: @yourcompany.com
    Bypass: from office IP 120.60.X.X
  Session: 24 hours

Step 7 — Logs and audit

Zero Trust → Logs → Access shows:

  • Who accessed what, when, from where
  • Failed auth attempts (useful for threat detection)
  • MFA challenges

Export to SIEM via Logpush (paid) or manually via API.

Cloudflare WARP for outbound

For fully zero-trust deploys, WARP agent on employee laptops forces all traffic through Cloudflare — including DNS queries. Adds malware filtering, DNS-based filtering of malicious sites, even from coffee-shop WiFi.

Common patterns

Pattern 1: Protect Grafana / internal dashboards

Grafana → Tunnel (localhost:3000) → Access policy (admins only) → grafana.yourcompany.com

No password on Grafana itself. Access is the gatekeeper. Grafana's auth_proxy module trusts the JWT identity.

Pattern 2: Partner extranet

External partners get invited via email. They sign in with one-time PIN. Policy restricts to specific URLs (/partner/*) only. Ticketing quick + no account provisioning burden.

Pattern 3: SSH via Access

Zero Trust can broker SSH connections too. Install cloudflared access ssh on laptops. No public SSH port needed on VPS. Every session auditable.

Migration — from password-protected admin to Zero Trust

  1. Set up Zero Trust + SSO (5 min)
  2. Create Access application for admin panel (2 min)
  3. Install cloudflared tunnel on VPS (5 min)
  4. Update DNS to proxy through Cloudflare
  5. Test with a test user
  6. Remove basic auth from origin (now redundant)
  7. Announce to team + share SSO login URL

Total migration: under 1 hour for a single app.

Common pitfalls

FAQ

Q Cost?

Free up to 50 users. Beyond that: $3/user/mo (teams up to 250) or $7/user/mo (unlimited + ZTNA features).

Q Zero Trust vs VPN?

Zero Trust is per-app authentication; VPN is network-level. Zero Trust is modern practice — narrower blast radius if a user is compromised.

Q Can I use Zero Trust with non-Cloudflare DNS?

You can use external DNS, but CF must proxy the traffic for policies to apply. Easier to move DNS to Cloudflare.

Q Does Tunnel slow my app?

Slightly (edge hop). 20-50ms added latency typical. For sub-100ms internal apps, acceptable.

Q Access with non-web protocols?

Access supports SSH, RDP, kubectl, databases via Cloudflare's Browser Isolation + WARP. Beyond scope of this article.

Front your DomainIndia internal apps with Cloudflare Zero Trust. See our hosting options

Was this article helpful?

Your feedback helps us improve our documentation

Still need help? Submit a support ticket