Skip to content

feat: add Cloudflare OAuth provider#529

Open
franklin-tina wants to merge 2 commits into
atinux:mainfrom
franklin-tina:feat/cloudflare-oauth
Open

feat: add Cloudflare OAuth provider#529
franklin-tina wants to merge 2 commits into
atinux:mainfrom
franklin-tina:feat/cloudflare-oauth

Conversation

@franklin-tina

@franklin-tina franklin-tina commented Jun 15, 2026

Copy link
Copy Markdown

Add Cloudflare OAuth provider

Adds a defineOAuthCloudflareEventHandler provider for signing in with a Cloudflare OAuth client, following the existing provider conventions.

Files in this PR (following existing patterns as other providers)

  • src/runtime/server/lib/oauth/cloudflare.ts
  • src/runtime/types/oauth-config.ts
  • src/module.tsruntimeConfig.oauth.cloudflare defaults (clientId / clientSecret / redirectURL)
  • Playground: login route, button, and User type entry
  • README: added to the Supported OAuth Providers list

Usage

export default defineOAuthCloudflareEventHandler({
  config: { scope: ['user-details.read'] }, // required — see note below on no default scopes
  async onSuccess(event, { user }) {
    await setUserSession(event, { user: { cloudflareId: user.sub } })
    return sendRedirect(event, '/')
  },
})

Environmnet variables:

NUXT_OAUTH_CLOUDFLARE_CLIENT_ID=
NUXT_OAUTH_CLOUDFLARE_CLIENT_SECRET=
# optionally if you want to override. 
# NUXT_OAUTH_CLOUDFLARE_REDIRECT_URL)=

Testing

  • Verified end-to-end against a live self-managed Cloudflare OAuth client: authorize → PKCE/state → token exchange → userinfo → session.
    Login succeeds and sub is returned.
  • Confirmed the access token authenticates against the Cloudflare REST API (/client/v4/user).
Screenshot 2026-06-14 at 19 14 31

Note

A couple of things I noticed while testing

  • No default scope. Cloudflare OAuth scopes are dot-notation API-permission IDs (e.g. user-details.read, workers-platform.read) fetched from GET /client/v4/oauth/scopes, and must match the scopes the client was registered with.
    Setting openid is rejected by self-managed clients despite being advertised in /.well-known/openid-configuration. (Don't know if I misread here)
  • Identity via /oauth2/userinfo returns sub plus standard OIDC claims (aud, iss, iat, auth_time, rat). no email/name. Profile data the OAuth access token works against GET /client/v4/user

Summary by CodeRabbit

New Features

  • Added Cloudflare as a supported OAuth authentication provider for user login, including the authorization flow and required scopes.

Documentation

  • Updated the README’s “Supported OAuth Providers” list to include Cloudflare.

Other Changes

  • Added Cloudflare-specific session and user field support, and added default runtime configuration for the Cloudflare OAuth provider.

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 33a0b5fb-290e-4a20-bc60-8dda21206277

📥 Commits

Reviewing files that changed from the base of the PR and between 27492d4 and 308c595.

📒 Files selected for processing (1)
  • src/runtime/server/lib/oauth/cloudflare.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/runtime/server/lib/oauth/cloudflare.ts

📝 Walkthrough

Walkthrough

Adds Cloudflare as an OAuth provider to the library. The implementation covers exported config/type interfaces, an Authorization Code + PKCE event handler, runtime config defaults, an updated OAuthProvider union type, a playground demo route and UI entry, an extended User type, and a README entry.

Changes

Cloudflare OAuth Provider

Layer / File(s) Summary
Core provider types, config defaults, and handler
src/runtime/server/lib/oauth/cloudflare.ts, src/runtime/types/oauth-config.ts, src/module.ts
Exports OAuthCloudflareConfig, CloudflareUser, and CloudflareTokens; adds cloudflare to the OAuthProvider union; registers runtimeConfig.oauth.cloudflare defaults (clientId, clientSecret, redirectURL); implements defineOAuthCloudflareEventHandler with PKCE challenge generation, state validation, token exchange via requestAccessToken, user-profile fetch, and onSuccess/onError routing.
Playground demo, User type extension, and README
playground/shared/types/auth.d.ts, playground/server/routes/auth/cloudflare.get.ts, playground/app/pages/index.vue, README.md
Extends the playground User interface with cloudflare?: string; adds a server route using defineOAuthCloudflareEventHandler with user-details.read scope that stores user.sub in the session; inserts the Cloudflare entry into the index page provider list; adds Cloudflare to the README supported providers list.

Sequence Diagram

sequenceDiagram
  participant Browser
  participant H3Handler as defineOAuthCloudflareEventHandler
  participant CloudflareAuth as Cloudflare /authorize
  participant CloudflareToken as Cloudflare /token
  participant CloudflareAPI as Cloudflare /user

  Browser->>H3Handler: GET /auth/cloudflare (no code)
  H3Handler->>H3Handler: generate state + PKCE verifier/challenge
  H3Handler-->>Browser: redirect → Cloudflare /authorize
  Browser->>CloudflareAuth: authorize (client_id, code_challenge, scope)
  CloudflareAuth-->>Browser: redirect → /auth/cloudflare?code=…&state=…
  Browser->>H3Handler: GET /auth/cloudflare?code=…&state=…
  H3Handler->>H3Handler: validate state
  H3Handler->>CloudflareToken: POST code + code_verifier
  CloudflareToken-->>H3Handler: access_token
  H3Handler->>CloudflareAPI: GET /user (Bearer token)
  CloudflareAPI-->>H3Handler: CloudflareUser
  H3Handler-->>Browser: onSuccess → set session, redirect /
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 A new cloud joins the provider parade,
With PKCE and tokens freshly made.
State checked, scope set, user.sub in tow,
The rabbit hops forth — watch the sessions grow!
☁️ Cloudflare's in — the list gains one more glow.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main change: adding Cloudflare as a new OAuth provider to the nuxt-auth-utils project.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/runtime/server/lib/oauth/cloudflare.ts`:
- Around line 115-117: The Cloudflare OAuth configuration validation incorrectly
requires both clientId and clientSecret to be present, blocking public PKCE-only
clients which don't need a client secret. Modify the validation check at line
115 to only require clientId and remove clientSecret from the required fields
list passed to handleMissingConfiguration. Additionally, update the token
request logic around lines 149-151 where clientSecret is sent to conditionally
include it only when config.clientSecret is present, allowing the request to
proceed without it for public clients using PKCE flow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fe3d7928-03f1-4637-add7-805a982e49dc

📥 Commits

Reviewing files that changed from the base of the PR and between ceb366b and 27492d4.

📒 Files selected for processing (7)
  • README.md
  • playground/app/pages/index.vue
  • playground/server/routes/auth/cloudflare.get.ts
  • playground/shared/types/auth.d.ts
  • src/module.ts
  • src/runtime/server/lib/oauth/cloudflare.ts
  • src/runtime/types/oauth-config.ts

Comment thread src/runtime/server/lib/oauth/cloudflare.ts Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant