Authentication
Overview
Section titled “Overview”Authentication is handled entirely by Cloudflare Access at the edge. No OAuth code, login pages, or session management exists in our codebase.
How It Works
Section titled “How It Works”- User visits
app.dotcollective.com.au - Cloudflare Access intercepts and shows Google Workspace login
- Only
@dotcollective.com.auemails are allowed (domain restriction) - After auth, Cloudflare injects a signed JWT via the
Cf-Access-Jwt-Assertionheader andCF_Authorizationcookie - Our Worker validates this JWT against the team’s certs endpoint (checks header first, falls back to cookie)
- User email and name are extracted from the JWT and upserted in D1 (name only on first login — user-set names are preserved)
What Cloudflare Access Handles
Section titled “What Cloudflare Access Handles”- Google OAuth flow, token exchange, session management
- Login UI and redirect flows
- Domain restriction enforcement (
@dotcollective.com.au) - Session cookie management and expiry
- OIDC claims forwarding (including Google profile picture via
pictureclaim)
What Our App Handles
Section titled “What Our App Handles”- JWT validation (
worker/lib/cf-access.ts) - Validates againsthttps://dotcollective.cloudflareaccess.com/cdn-cgi/access/certs - User management - Auto-creates users in D1 on first login, preserves user edits on subsequent visits
- Profile picture sync - On first login, fetches Google profile picture from
/cdn-cgi/access/get-identityOIDC claims and saves to D1 - Access levels - Assigns roles (Executive, Head, Manager, Lead, Employee)
- Tool permissions - Per-tool view/update/manage grants
- Frontend auth context - Fetches
/api/users/mefor UI permissions
Cloudflare Access OIDC Configuration
Section titled “Cloudflare Access OIDC Configuration”The Google IdP in Cloudflare Zero Trust must have picture added as an OIDC claim. This makes the Google profile photo URL available in the /cdn-cgi/access/get-identity response under oidc_fields.picture.
Profile Page
Section titled “Profile Page”Users can edit their display name at /profile. The name is preserved across logins (the auth middleware only sets the name on initial user creation, not on subsequent visits).
Local Development
Section titled “Local Development”Cloudflare Access is not present locally. The app provides a dev user picker at localhost:5173:
- On load,
GET /api/dev/usersfetches all existing users (unauthenticated endpoint) - The picker shows existing users with avatars and access level badges
- Selecting a user (or entering a new email) stores the email in
localStorage - All subsequent API calls include a
CF-Access-Mock-Emailheader via theapiFetchwrapper - The auth middleware accepts this header and impersonates the user
- “Switch user” in the user menu clears the selection and returns to the picker