Skip to content

Cloudflare Access

Cloudflare Access users are linked by the verified Access issuer and subject, never by email alone. An Access user is an interactive product user: workspace permissions come from the same owner/admin/member/viewer membership matrix as a Better Auth session. The selected workspace is stored server-side and restored on later requests. Users with no memberships receive one idempotently provisioned owner workspace; this does not grant instance-administrator status or a short-link domain.

Use the workspace switcher for browser selection. It calls PUT /api/workspaces/active; neither the switcher nor any browser credential is stored in local storage. A configured Access service identity is restricted to explicit machine-oriented /api/admin/** operations and does not get workspace membership or a dashboard UI.

Cloudflare Access is optional. Use it when you want people to sign in to the dashboard with your company identity (Google, email OTP, SSO, and so on) instead of only sharing NUXT_SITE_TOKEN.

Short links stay public either way. Access only affects who can open the dashboard and call the API.

What changes after you enable it

PathWithout AccessWith recommended Access setup
Short links (/abc)PublicStill public
Dashboard (/dashboard)Anyone with the site tokenMust pass Cloudflare Access first, then use the dashboard
API (/api/**)Site token (Bearer …)Site token or a valid Access login (browser cookie / JWT)
API docs (/_docs)Public on your hostStill public unless you protect it separately in Access

Set never trusts “there is a cookie”. It verifies the Access JWT — think of it as a short-lived electronic pass (signature, issuer, audience, and expiry are all checked).

Goal: protect the dashboard with Access, keep short links public, and still allow scripts/extensions to use the site token on /api.

1. Create an Access application

In Cloudflare Zero Trust, create a self-hosted Access application for your Set hostname (for example links.example.com).

2. Choose which paths Access protects

In the Access application path rules:

PathProtect with Access?Why
/dashboard and childrenYesThis is the admin UI
/apiNo (recommended)Lets site-token clients (scripts, extensions) call the API without going through Access
Short-link pathsNoVisitors must open short links freely
/_docsOptionalProtect only if you do not want OpenAPI public

In the Access application settings, keep Cookie Path disabled / empty so the signed Access cookie can reach /api when the browser calls the API from the dashboard.

If Cookie Path is limited to /dashboard only, the dashboard may load but API calls can fail with 401.

4. Set Set environment variables

Both values are required. Access is enabled only when both are set:

ini
NUXT_CF_ACCESS_TEAM_DOMAIN=https://your-team.cloudflareaccess.com
NUXT_CF_ACCESS_AUD=paste-application-aud-here
VariableWhere to get it
NUXT_CF_ACCESS_TEAM_DOMAINYour Zero Trust team domain. Use the full origin, no path: https://<team>.cloudflareaccess.com
NUXT_CF_ACCESS_AUDAccess application → Application Audience (AUD) Tag

Redeploy after setting them.

5. Keep a strong site token

Even with Access, keep a strong NUXT_SITE_TOKEN:

  • API clients and integrations still use it
  • It is a backup admin credential
  • Any hostname that reaches this Worker/Pages app can still accept the site token unless Access blocks that path at the edge

How people and tools sign in

txt
Browser → Access login page → dashboard
         ↘ Access cookie/JWT → Set verifies it → /api works

Script/extension → Authorization: Bearer <NUXT_SITE_TOKEN> → /api works
  • People (browser): pass Access, then use the dashboard as usual. Logout goes through Cloudflare (/cdn-cgi/access/logout).
  • Tools (API): send Authorization: Bearer YOUR_SITE_TOKEN. Prefer this for automation.
  • Access service tokens: if allowed by your Access policy, Set treats them as full admin (root). Only allow trusted service tokens.

Stricter option: protect /api too

You can put both /dashboard and /api behind Access.

Then Cloudflare blocks unauthenticated requests before they reach Set. Site-token-only clients cannot call that hostname unless they also satisfy Access.

If you need both:

  • human dashboard behind Access, and
  • simple Bearer-token automation without Access,

use the recommended setup above, or put automation on a separate hostname that is not Access-protected.

Important limits

Protect every hostname

If app.example.com is behind Access but old.example.com points at the same Set deployment without Access, the old host is still only as safe as NUXT_SITE_TOKEN. Protect every hostname that reaches the app.

Session length still matters

Set checks the JWT locally. If you revoke an Access session, the old JWT can work until it expires. Pick an Access session duration that fits your risk.

Cloudflare references