Puts Continue with Cloudflare on the Gateway's sign-in page, beside
the password, for the members of the person's Cloudflare account. At the
end the person has a private OAuth client in that account, its two
settings on the Gateway, and has signed in with Cloudflare once.
pnpm everyapp signin show cloudflare --json names this guide as setup,
and the CLI prints Guide: https://everyapp.com/docs/agent/setup/signin-cloudflare.md.
Who gets in doesn't change: Cloudflare only says who someone is. A member
of the Gateway signs in; someone with a pending invitation for that exact
address joins with the invited role; everyone else is refused ("You don't
have an account on this gateway.") and nothing is created. An existing
password account connects Cloudflare once, by signing in with the password
when the page asks. The rules: docs/runbooks/sign-in-providers.md.
Keep the client private (the default). Cloudflare's /user answer has
no "verified" flag; the address is trusted only because a private client
can be authorized by nobody but the Cloudflare account's members, who got
in by accepting an invitation sent to that address. Making a client public
is permanent and would let any Cloudflare user present an address nobody
checked. Everyone outside the Cloudflare account uses another provider, a
password, or Access's one-time PIN.
Not the same as Access's "Sign in with Cloudflare" (access.md):
that one is a login in front of the Gateway, at Cloudflare's edge, for
every page and app. This one is a button on the Gateway's sign-in page,
like Google's. Both can be on; with Access on, this button is rarely needed.
No price on Cloudflare's OAuth client page, and no plan named (free as far
as checked; unverified). Creating a client needs the Super Administrator,
Administrator or OAuth Client Write role on the account.
pnpm everyapp status --json: data.installed and data.claimed true;
data.gatewayUrl gives <gateway host>. Not installed or no owner:
gateway.md first. data.access.on true: see Verify 4.
pnpm everyapp signin show cloudflare --json (changes nothing;
Unknown command signin: git pull in the every-app folder).
data.statusoff: this guide applies; needs setup: data.missing
says what is left (step 3); on: ask before replacing.
data.callbackUrl is https://<gateway host>/api/auth/callback/cloudflare.
Ask who should use it: only people who are members of their Cloudflare
account can. For anyone else, suggest Google, Microsoft or the password.
Person: in the Cloudflare dashboard, the account the Gateway runs
in: https://dash.cloudflare.com/?to=/:account/oauth-clients (or
Manage Account → OAuth clients) → Create client. Client name
(EveryApp); response type code, grant type Authorization Code;
token authentication method client_secret_basic; redirect URL the
exact URL from step 1 → Continue → scopes: User Details Read,
left Required (an optional one can be declined, and then sign-in
can't finish) → Create client. The page shows the Client ID and
the Client Secret, the secret only now. Leave its visibility
private: never Change Visibility.
Person: in a second terminal in the every-app folder:
pnpm everyapp signin add cloudflare
It asks for the Client ID (shown as typed) and the Client Secret
(hidden: pasting works, nothing is echoed), and writes both in one new
Gateway Worker version, live on the next request. They tell you when
it's done.
Another way: in that terminal, the hidden read (bash or zsh:
read -rs CLOUDFLARE_SIGNIN_CLIENT_SECRET && export CLOUDFLARE_SIGNIN_CLIENT_SECRET;
fish: read -s -x CLOUDFLARE_SIGNIN_CLIENT_SECRET), paste, Enter, then
pnpm everyapp signin add cloudflare --client-id <Client ID> --client-secret-from-env CLOUDFLARE_SIGNIN_CLIENT_SECRET --json
and unset CLOUDFLARE_SIGNIN_CLIENT_SECRET (fish: set -e CLOUDFLARE_SIGNIN_CLIENT_SECRET).
pnpm everyapp signin list --json: the cloudflare entry has status: "on" and missing empty.
The person's Cloudflare login address must be a Gateway member's or
have a pending invitation: pnpm everyapp workspace invite <email> for
someone new (who must also be a member of the Cloudflare account).
Person: private window, https://<gateway host>/sign-in →
Continue with Cloudflare → Cloudflare's login → the consent screen
→ allow → the Gateway, signed in.
Behind Cloudflare Access: nothing else changes, but the Cloudflare
address must be the one Access knows the person by.
Logs (the setup rules' Verify 4): signin.config_problem for a malformed or
missing setting.
Rerun: pnpm everyapp signin add cloudflare any time; values given
replace, settings not given are kept (Enter at a prompt keeps it).
Rotate: rotate the secret on the client's page in the dashboard (a lost
secret can only be rotated), then pnpm everyapp signin add cloudflare
with Enter at the Client ID prompt, or the hidden read and
pnpm everyapp signin add cloudflare --client-secret-from-env CLOUDFLARE_SIGNIN_CLIENT_SECRET --json.
Remove, only when asked: pnpm everyapp signin remove cloudflare --json --yes
(--yes only when they said so). Accounts made with it stay. Then
delete the client in Manage Account → OAuth clients.
docs/runbooks/sign-in-providers.md ("Cloudflare", "Sign in with
Cloudflare: Access's identity provider versus this") and
packages/sdk/src/internal/signInProviders.ts