Skip to content

feat: Login with Cloudflare + Security Fixes#397

Open
karishnu wants to merge 4 commits into
stagingfrom
feat/vibe-22-cloudflare-login-ai-gateway-toggle
Open

feat: Login with Cloudflare + Security Fixes#397
karishnu wants to merge 4 commits into
stagingfrom
feat/vibe-22-cloudflare-login-ai-gateway-toggle

Conversation

@karishnu

@karishnu karishnu commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

feat: Login with Cloudflare + per-user AI Gateway toggle

Summary

Adds "Login with Cloudflare" as a first-class OAuth identity provider, with the same consent optionally auto-connecting the user's Cloudflare AI Gateway in a single round-trip. Adds a per-user "Use my AI Gateway" toggle so users decide whether generations run on their own Cloudflare credits or the platform's free tier. Also includes related security hardening (login-CSRF / open-forward / account-hijack chain), a refactor that hardcodes the Cloudflare OAuth scopes and endpoint URLs, and gates the AI Gateway feature on CF_OAUTH_ENCRYPTION_KEY.

Motivation

  • Reduce onboarding friction: users can sign in with Cloudflare and have their AI Gateway connected automatically.
  • Give users explicit control over whether their own gateway/credits are used.
  • Close a login-CSRF → open-forward → account-linking abuse chain.

What's included

1. Login with Cloudflare (identity)

  • cloudflare added to the OAuth provider union, Zod schema, and authAttempts enum (oauth_cloudflare).
  • CloudflareConnectOAuthProvider.createForLogin() builds an identity provider that redirects to /api/auth/callback/cloudflare.
  • getUserInfo hardened to read the Cloudflare API v4 { result: {...} } envelope (unwraps result, composes name from first_name/last_name) and to require a real email for login (no unknown@cloudflare.local fallback).
  • Frontend: "Continue with Cloudflare" button in login-modal, plus auth-context, auth-button, AuthModalProvider widened to google | github | cloudflare. Button shows whenever the OAuth client ID/secret are configured.

2. AI Gateway auto-connect on login

  • On the Cloudflare login callback, AuthService surfaces the raw provider tokens (Cloudflare only) and the controller performs a best-effort gateway provision + encrypted token-cookie set.
  • Failure never blocks identity login. Skipped entirely unless the gateway feature is enabled.
  • Provisioning logic extracted into a shared CloudflareProvisioningService used by both the standalone connect flow and the login auto-connect.

3. Per-user "Use my AI Gateway" toggle

  • New nullable users.ai_gateway_enabled column (migration 0006_free_wiccan.sql). null = derived default: off for Cloudflare-login users, on for users who explicitly connected.
  • UserService.getAiGatewayPreference() (returns { enabled, isExplicit }) / setAiGatewayPreference().
  • Gating centralized in usageChecker: hasCloudflareConfigured and getUserGateway return false/null when the toggle is off, so the platform gateway and rate limits apply.
  • New endpoints GET/PUT /api/cloudflare/ai-gateway-preference; /api/limits/usage now also returns aiGatewayConnected, aiGatewayEnabled, aiGatewayPreferenceExplicit.
  • Settings UI: a Switch in cloudflare-account-selector with optimistic update + rollback.

4. Security hardening

  • Login CSRF / session fixation: OAuth state is now bound to the initiating browser via an HttpOnly nonce cookie (__Host-oauth_nonce); the callback rejects mismatched/absent nonces. Applies to all providers.
  • Open-forward: validateRedirectUrl now blocks /oauth/ and /auth/ paths and rejects nested return_url/redirect_url/continue params.
  • Defense-in-depth: the callback re-validates the stored redirect URL.
  • Session freshness gate: linking a Cloudflare account requires a session younger than 5 min (new SessionService.getSessionCreatedAt).
  • Transactional disconnect: CloudflareAccountService.deleteAllForUser batch-deletes gateway + account rows so a revoked connection leaves no stale state.

5. Config refactor

  • Cloudflare OAuth scopes (openid user-details.read ai.read ai.write aig.read aig.run aig.write offline_access) and endpoint URLs are now hardcoded constants in cloudflare-connect.ts — removed CLOUDFLARE_OAUTH_SCOPES/_AUTH_URL/_TOKEN_URL/_USERINFO_URL env vars and typings.
  • CF_OAUTH_ENCRYPTION_KEY is now required for the AI Gateway feature: isCloudflareGatewayLimitsEnabled returns false without it (same as ENABLE_CLOUDFLARE_LIMITS unset). Identity login still works without the key; only the gateway auto-connect is skipped.

6. Docs

  • docs/setup.md gains a Login with Cloudflare section: dashboard link to create OAuth clients (https://dash.cloudflare.com/?to=/:account/oauth-clients), required redirect URLs, the scope string, and the env vars (clarifying which are needed for login vs. AI Gateway).

Configuration for self-deployers

# Login with Cloudflare (identity only)
CLOUDFLARE_OAUTH_CLIENT_ID="..."
CLOUDFLARE_OAUTH_CLIENT_SECRET="..."

# Additionally for AI Gateway connect/auto-connect
ENABLE_CLOUDFLARE_LIMITS="true"
CF_OAUTH_ENCRYPTION_KEY="$(openssl rand -base64 32)"

OAuth client redirect URLs:

  • https://<origin>/api/auth/callback/cloudflare — Login with Cloudflare
  • https://<origin>/auth/callback — connect AI Gateway from settings

Database migration

migrations/0006_free_wiccan.sql adds users.ai_gateway_enabled. Apply with:

  • Local: npm run db:migrate:local
  • Remote: npm run db:migrate:remote

Testing

  • npm run typecheck and npm run lint pass.
  • Existing pre-commit test suite (21 tests) passes.
  • Manual verification of the OAuth round-trip requires a configured Cloudflare OAuth client.

Risk / rollback

  • New DB column is nullable and additive; safe to roll forward. The feature is inert unless the Cloudflare OAuth env vars are set.
  • Security changes (nonce binding, redirect re-validation) affect all OAuth providers — worth a focused review of Google/GitHub login during QA.

@github-actions github-actions Bot added documentation Improvements or additions to documentation worker frontend database size/XL labels Jun 26, 2026
@ask-bonk

ask-bonk Bot commented Jun 26, 2026

Copy link
Copy Markdown

Model not found: cloudflare-ai-gateway/google-ai-studio/gemini-3-pro-preview. Did you mean: openai/o3-pro, workers-ai/@cf/google/gemma-3-12b-it, anthropic/claude-3-5-haiku?

github run

@ask-bonk

ask-bonk Bot commented Jun 26, 2026

Copy link
Copy Markdown

@karishnu Bonk workflow failed. Check the logs for details.

View workflow run · To retry, trigger Bonk again.

- Add Cloudflare as an OAuth login provider with AI Gateway auto-connect
  in the same round-trip; harden userinfo email resolution (v4 envelope).
- Add per-user AI Gateway usage toggle (nullable users.ai_gateway_enabled,
  derived default: off for Cloudflare-login users, on for others) gating
  hasCloudflareConfigured/getUserGateway and surfaced via /api/limits/usage
  and a new /api/cloudflare/ai-gateway-preference endpoint + settings switch.
- Security hardening: OAuth nonce cookie binding, redirect-URL re-validation,
  session freshness gate on connect, transactional Cloudflare disconnect.
- Extract shared CloudflareProvisioningService; add migration 0006.

VIBE-22

refactor: hardcode Cloudflare OAuth scopes/URLs and gate AI Gateway on encryption key (VIBE-22)

- Hardcode Cloudflare OAuth scopes and endpoint URLs in cloudflare-connect.ts;
  remove CLOUDFLARE_OAUTH_SCOPES/_AUTH_URL/_TOKEN_URL/_USERINFO_URL env vars.
- Treat a missing CF_OAUTH_ENCRYPTION_KEY as the AI Gateway feature being
  disabled (isCloudflareGatewayLimitsEnabled also checks the key).
- Keep identity Login with Cloudflare working without the key; the gateway
  auto-connect in the login callback is skipped unless the feature is enabled.
- Document Login with Cloudflare setup (OAuth client, redirect URLs, scopes,
  env vars) in docs/setup.md.
@karishnu karishnu force-pushed the feat/vibe-22-cloudflare-login-ai-gateway-toggle branch from 31685e7 to 4467a0e Compare June 26, 2026 10:33
@ask-bonk

ask-bonk Bot commented Jun 26, 2026

Copy link
Copy Markdown

Model not found: cloudflare-ai-gateway/google-ai-studio/gemini-3-pro-preview. Did you mean: openai/o3-pro, workers-ai/@cf/google/gemma-3-12b-it, anthropic/claude-3-5-haiku?

github run

@karishnu karishnu changed the title Feat/vibe 22 cloudflare login ai gateway toggle feat: Login with Cloudflare + Security Fixes Jun 26, 2026
- Add user_oauth_identities table; resolve OAuth logins by (provider, providerId)
- Gate logins on provider-verified email; hard-reject email collisions (409)
- Stop GitHub provider hardcoding emailVerified; report actual verification
- Default Cloudflare emailVerified when absent so gate does not regress login
- Add authenticated link/unlink/list identity endpoints + client methods
- Add CONFLICT SecurityErrorType; backfill migration for existing OAuth users
@ask-bonk

ask-bonk Bot commented Jul 2, 2026

Copy link
Copy Markdown

Model not found: cloudflare-ai-gateway/google-ai-studio/gemini-3-pro-preview. Did you mean: openai/o3-pro, workers-ai/@cf/google/gemma-3-12b-it, anthropic/claude-3-5-haiku?

github run

The OAuth callback bypassed the deployment email allowlist, letting any OAuth account obtain a session on deployments configured to gate signups.

Centralize the check in a shared enforceAllowedEmail helper applied inside AuthService for register, login, OAuth callback, and email verification. It runs before any user row or session is created and compares case-insensitively. Removes the redundant inline controller checks.
@ask-bonk

ask-bonk Bot commented Jul 2, 2026

Copy link
Copy Markdown

Model not found: cloudflare-ai-gateway/google-ai-studio/gemini-3-pro-preview. Did you mean: openai/o3-pro, workers-ai/@cf/google/gemma-3-12b-it, anthropic/claude-3-5-haiku?

github run

Surface the multi-provider identity endpoints in the UI:
- New ConnectedAccounts component lists linked OAuth providers with
  link/unlink actions and verified badges
- Handles link callback redirect params (?linked/?error) with toasts
- Replaces the static single-provider block in the Security section

Relocate SessionResponse type from authUtils.ts to auth-types.ts so the
frontend no longer type-checks worker runtime code (fixes app-project
build error on the Env global).
@ask-bonk

ask-bonk Bot commented Jul 6, 2026

Copy link
Copy Markdown

Model not found: cloudflare-ai-gateway/google-ai-studio/gemini-3-pro-preview. Did you mean: openai/o3-pro, workers-ai/@cf/google/gemma-3-12b-it, anthropic/claude-3-5-haiku?

github run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

database documentation Improvements or additions to documentation frontend size/XL worker

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants