feat: Login with Cloudflare + Security Fixes#397
Conversation
|
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? |
|
@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.
31685e7 to
4467a0e
Compare
|
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? |
- 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
|
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? |
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.
|
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? |
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).
|
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? |
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
What's included
1. Login with Cloudflare (identity)
cloudflareadded to the OAuth provider union, Zod schema, andauthAttemptsenum (oauth_cloudflare)./api/auth/callback/cloudflare.{ result: {...} }envelope (unwrapsresult, composes name fromfirst_name/last_name) and to require a real email for login (nounknown@cloudflare.localfallback).login-modal, plusauth-context,auth-button,AuthModalProviderwidened togoogle | github | cloudflare. Button shows whenever the OAuth client ID/secret are configured.2. AI Gateway auto-connect on login
AuthServicesurfaces the raw provider tokens (Cloudflare only) and the controller performs a best-effort gateway provision + encrypted token-cookie set.CloudflareProvisioningServiceused by both the standalone connect flow and the login auto-connect.3. Per-user "Use my AI Gateway" toggle
users.ai_gateway_enabledcolumn (migration0006_free_wiccan.sql).null= derived default: off for Cloudflare-login users, on for users who explicitly connected.UserService.getAiGatewayPreference()(returns{ enabled, isExplicit }) /setAiGatewayPreference().usageChecker: hasCloudflareConfigured and getUserGateway return false/null when the toggle is off, so the platform gateway and rate limits apply.GET/PUT /api/cloudflare/ai-gateway-preference;/api/limits/usagenow also returnsaiGatewayConnected,aiGatewayEnabled,aiGatewayPreferenceExplicit.Switchincloudflare-account-selectorwith optimistic update + rollback.4. Security hardening
stateis now bound to the initiating browser via an HttpOnly nonce cookie (__Host-oauth_nonce); the callback rejects mismatched/absent nonces. Applies to all providers.validateRedirectUrlnow blocks/oauth/and/auth/paths and rejects nestedreturn_url/redirect_url/continueparams.SessionService.getSessionCreatedAt).CloudflareAccountService.deleteAllForUserbatch-deletes gateway + account rows so a revoked connection leaves no stale state.5. Config refactor
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 — removedCLOUDFLARE_OAUTH_SCOPES/_AUTH_URL/_TOKEN_URL/_USERINFO_URLenv vars and typings.CF_OAUTH_ENCRYPTION_KEYis now required for the AI Gateway feature: isCloudflareGatewayLimitsEnabled returns false without it (same asENABLE_CLOUDFLARE_LIMITSunset). Identity login still works without the key; only the gateway auto-connect is skipped.6. Docs
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
OAuth client redirect URLs:
https://<origin>/api/auth/callback/cloudflare— Login with Cloudflarehttps://<origin>/auth/callback— connect AI Gateway from settingsDatabase migration
migrations/0006_free_wiccan.sqladdsusers.ai_gateway_enabled. Apply with:npm run db:migrate:localnpm run db:migrate:remoteTesting
npm run typecheckandnpm run lintpass.Risk / rollback