Zero Trust & API Access
What Is Cloudflare Zero Trust
The arc subdomains (internal API) are protected by Cloudflare Zero Trust Access. It sits in front of the origin server at the Cloudflare edge — every request is validated before it reaches the backend. Requests without valid credentials are rejected with 403 Forbidden and never reach the origin.
This is not just obscurity (a hard-to-guess URL). Zero Trust actively rejects all unauthorised traffic at the network level.
Service Tokens
Access to the API uses Service Tokens — machine-to-machine credentials generated in Cloudflare → Zero Trust → Access → Service Auth.
Each token consists of two values:
- Client ID — stored as
VITE_CF_ACCESS_CLIENT_ID - Client Secret — stored as
VITE_CF_ACCESS_CLIENT_SECRET
A separate token exists per environment:
| Environment | Protects | Token Stored In |
|---|---|---|
| Staging | staging-arc.semalink.africa | GitHub Environment staging |
| Test | test-arc.semalink.africa | GitHub Environment test |
| Production | arc.semalink.africa | GitHub Environment prod |
How the Frontend Authenticates
The two token values are baked into the app bundle at build time. The Axios HTTP client attaches them as headers on every API request:
// src/core/api/client.ts
import axios from 'axios'
const client = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
headers: {
'CF-Access-Client-Id': import.meta.env.VITE_CF_ACCESS_CLIENT_ID,
'CF-Access-Client-Secret': import.meta.env.VITE_CF_ACCESS_CLIENT_SECRET,
},
})
export default clientCloudflare validates the headers at the edge on every request. If they match, the request is proxied to the origin. If they are missing or incorrect, Cloudflare returns 403.
Request Flow
Frontend App
↓ (HTTP request with CF-Access headers)
Cloudflare Edge
↓ Validates service token
├── Valid → proxied to backend origin
└── Invalid → 403 Forbidden (origin never contacted)Rotating a Service Token
- Go to Cloudflare → Zero Trust → Access → Service Auth
- Select the token → Roll Credentials
- Copy the new Client ID and Client Secret
- Update
VITE_CF_ACCESS_CLIENT_IDandVITE_CF_ACCESS_CLIENT_SECRETin the GitHub Environment - Trigger a new deployment — the new token will be baked into the next build
Pending Setup
Access Application policies still need to be created for each arc subdomain in Cloudflare → Zero Trust → Access → Applications. Until these policies are in place, Zero Trust will not actively enforce the token check. See the post-setup checklist.