Follow these steps to replace the bearer-token auth with Cloudflare Access service tokens.
- Access to the Cloudflare dashboard at https://dash.cloudflare.com
- Your account must be on a plan that includes Cloudflare Access (Zero Trust). The free tier includes Access for up to 50 users/service tokens — this should cover personal use.
- In the Cloudflare dashboard, click Zero Trust in the left sidebar (or navigate to https://one.dash.cloudflare.com).
- If prompted, complete the Zero Trust onboarding (choose a team name, e.g.
mattjacobs). This becomes your team domain:mattjacobs.cloudflareaccess.com. Write it down — you will need it in Step 4.
- In Zero Trust, go to Access → Applications.
- Click Add an application.
- Choose Self-hosted.
- Fill in the form:
- Application name:
serverless-memex - Session Duration:
24 hours(or whatever you prefer; service tokens ignore session duration but it is required) - Application domain:
serverless-memex.mattjacobs.workers.dev- Subdomain:
serverless-memex - Domain:
mattjacobs.workers.dev - Path: (leave blank to cover all paths)
- Subdomain:
- Application name:
- Click Next.
- On the Policies step, click Add a policy.
- Fill in:
- Policy name:
service-token-access - Action:
Service Auth(this is the option specifically for machine-to-machine service tokens — it does NOT prompt for a login page) - Under Configure rules, set:
- Include → rule type: Service Token → select the token you will create in Step 4 (you may need to create it first and come back, or proceed and edit the policy afterward)
- Policy name:
- Click Save policy, then Next, then Add application.
If the UI requires selecting a token at policy creation time, complete Step 4 first, then come back and add the policy.
-
In Zero Trust, go to Access → Service Auth → Service Tokens.
-
Click Create Service Token.
-
Fill in:
- Service Token name:
memex-cli - Service Token Duration:
Non-expiring(or set a rotation schedule if preferred)
- Service Token name:
-
Click Generate token.
-
IMPORTANT: Copy both values immediately — the Secret is only shown once:
- Client ID: looks like
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.access - Client Secret: a long random string
- Client ID: looks like
-
Save them in
~/.secrets:MEMEX_CLIENT_ID=<paste Client ID here> MEMEX_CLIENT_SECRET=<paste Client Secret here>
-
Go back to the policy created in Step 3 and confirm the
memex-clitoken is selected in the Service Token rule. Save if needed.
The Worker must know your CF Access team domain to verify JWTs. Add it as a Wrangler variable:
cd ~/dev/projects/serverless-memex
set -a && source .secrets && set +a
pnpm exec wrangler secret put CF_TEAM_DOMAINWhen prompted, enter your team domain without the https:// prefix, e.g.:
mattjacobs.cloudflareaccess.com
cd ~/dev/projects/serverless-memex
set -a && source .secrets && set +a
pnpm exec wrangler deployTest that unauthenticated requests are rejected:
curl -sS -o /dev/null -w "%{http_code}" https://serverless-memex.mattjacobs.workers.dev/search \
-X POST -H "Content-Type: application/json" -d '{"query":"test"}'
# Expected: 401Test that authenticated requests succeed:
source ~/.secrets
curl -sS -X POST https://serverless-memex.mattjacobs.workers.dev/search \
-H "CF-Access-Client-Id: $MEMEX_CLIENT_ID" \
-H "CF-Access-Client-Secret: $MEMEX_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{"query":"test"}' | jq .Then test the shell functions:
echo "test capture" | memex-capture
memex-search "test"Once Access is working, delete the now-unused AUTH_SECRET Wrangler secret:
cd ~/dev/projects/serverless-memex
set -a && source .secrets && set +a
pnpm exec wrangler secret delete AUTH_SECRET- The Worker verifies the
Cf-Access-Jwt-AssertionJWT that Cloudflare Access injects. It fetches CF's JWKS fromhttps://<team-domain>/cdn-cgi/access/certsand caches the public keys in memory for the lifetime of the isolate. - If you see
401 Unauthorizedafter setup, check that: (a) the service token is attached to a Service Auth policy (not a regular Allow policy), (b)CF_TEAM_DOMAINis set correctly (no trailing slash, nohttps://), and (c) you sourced~/.secretsso the shell functions have the new env vars. - The old
MEMEX_TOKENvariable in~/.secretsis no longer needed and can be removed once everything is verified working.