Skip to content

[wrangler] Add experimental OAuth 2.0 Device Authorization Grant support#14064

Draft
petebacondarwin wants to merge 1 commit into
mainfrom
pbacondarwin/wrangler-oauth-device-flow
Draft

[wrangler] Add experimental OAuth 2.0 Device Authorization Grant support#14064
petebacondarwin wants to merge 1 commit into
mainfrom
pbacondarwin/wrangler-oauth-device-flow

Conversation

@petebacondarwin

@petebacondarwin petebacondarwin commented May 27, 2026

Copy link
Copy Markdown
Contributor

Adds an experimental --experimental-device flag to wrangler login that uses the OAuth 2.0 Device Authorization Grant (RFC 8628) instead of the existing localhost callback flow.

Replaces #13130 with an industry standard approach.
Fixes #13117
Fixes #10935

Note

Ready for code review, not yet ready to merge. The flag is gated behind --experimental-device and is inert in production until the supporting server-side work ships (see Dependencies below). Kept as a Draft until then.

What this changes

wrangler login --experimental-device runs a new flow that:

  • requests a device code + user code from the OAuth device authorization endpoint,
  • prints the verification URL and user code to the terminal,
  • attempts to open the verification URL in the user's default browser,
  • prints a QR code of the verification URL so the user can scan it with their phone,
  • polls the token endpoint with grant_type=urn:ietf:params:oauth:grant-type:device_code until the user approves the request, denies it, or the device code expires.

This is useful in containers, remote SSH sessions, Codespaces, and any other environment where localhost:8976 is unreachable from the user's browser.

Where the code lives

Since this PR was first opened, wrangler's OAuth machinery was extracted into the @cloudflare/workers-auth package (#14185). This PR is rebased onto that structure:

  • The device-flow primitives live in @cloudflare/workers-auth, exposed through the existing createOAuthFlow(...) API as a new device login option. Other Cloudflare CLIs that consume the package get the flow for free.
  • wrangler wires up the --experimental-device flag and injects its QR renderer + client config into the flow context.
  • The QR renderer is injected via the flow context (renderDeviceQrCode), mirroring the existing generateAuthUrl / generateRandomState test-injection seam, so the device-flow snapshot tests stay deterministic.

Behaviour details

  • Initial poll is sent immediately with no wait, so logins that complete before the QR finishes rendering feel instantaneous.
  • Subsequent polls respect the server's interval field (RFC 8628 §3.5), with a minimum floor of 1s. If the server sends slow_down, we add +5s as required by the RFC.
  • Wrangler-side hard cap of 5 minutes on top of the server's expires_in, to limit the abuse window if a user code is ever leaked (RFC 8628 §5.4).
  • --callback-host and --callback-port are rejected (hard error) when --experimental-device is set — this flow has no local callback server.
  • offline_access scope is appended unconditionally, same as the auth-code flow, so refresh tokens still work end-to-end.
  • Polling does not spam stderr: HTTP 400 with authorization_pending / slow_down is the expected RFC 8628 §3.5 control mechanism, so the poll path logs non-2xx responses at debug level only — a normal pending login produces no error output.
  • The device authorization endpoint is not environment-overridable; it derives from the same auth domain as the token endpoint (production vs. staging), so the device-auth and token endpoints can never desync.

Why "experimental"

This is gated behind --experimental-device so we can iterate on UX (polling cadence, timeout messaging, QR rendering, etc.) before committing to the surface. There is no auto-detection or fallback from the existing flow — users have to opt in explicitly.

Dependencies

This is the client-side (Wrangler) portion. It is safe to land independently because the flag is experimental and opt-in, but the end-to-end flow only works in production once the supporting server-side work ships:


@changeset-bot

changeset-bot Bot commented May 27, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 9c81731

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@cloudflare/workers-auth Minor
wrangler Minor
@cloudflare/vite-plugin Patch
@cloudflare/vitest-pool-workers Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actions Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor

✅ All changesets look good

ask-bonk[bot]

This comment was marked as resolved.

@ask-bonk

This comment was marked as outdated.

@pkg-pr-new

pkg-pr-new Bot commented May 27, 2026

Copy link
Copy Markdown
create-cloudflare

npm i https://pkg.pr.new/create-cloudflare@14064

@cloudflare/deploy-helpers

npm i https://pkg.pr.new/@cloudflare/deploy-helpers@14064

@cloudflare/kv-asset-handler

npm i https://pkg.pr.new/@cloudflare/kv-asset-handler@14064

miniflare

npm i https://pkg.pr.new/miniflare@14064

@cloudflare/pages-shared

npm i https://pkg.pr.new/@cloudflare/pages-shared@14064

@cloudflare/unenv-preset

npm i https://pkg.pr.new/@cloudflare/unenv-preset@14064

@cloudflare/vite-plugin

npm i https://pkg.pr.new/@cloudflare/vite-plugin@14064

@cloudflare/vitest-pool-workers

npm i https://pkg.pr.new/@cloudflare/vitest-pool-workers@14064

@cloudflare/workers-auth

npm i https://pkg.pr.new/@cloudflare/workers-auth@14064

@cloudflare/workers-editor-shared

npm i https://pkg.pr.new/@cloudflare/workers-editor-shared@14064

@cloudflare/workers-utils

npm i https://pkg.pr.new/@cloudflare/workers-utils@14064

wrangler

npm i https://pkg.pr.new/wrangler@14064

commit: 9c81731

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 5 additional findings.

Open in Devin Review

@petebacondarwin petebacondarwin force-pushed the pbacondarwin/wrangler-oauth-device-flow branch from d604f3f to ea3cd3d Compare June 12, 2026 12:19

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Devin Review found 2 new potential issues.

Open in Devin Review

Comment thread packages/workers-auth/package.json Outdated
Comment thread packages/wrangler/src/user/commands.ts
@petebacondarwin petebacondarwin force-pushed the pbacondarwin/wrangler-oauth-device-flow branch from ea3cd3d to b6ac62c Compare June 12, 2026 12:49
devin-ai-integration[bot]

This comment was marked as resolved.

@petebacondarwin petebacondarwin force-pushed the pbacondarwin/wrangler-oauth-device-flow branch from b6ac62c to 6318f88 Compare June 12, 2026 13:06
devin-ai-integration[bot]

This comment was marked as resolved.

@petebacondarwin petebacondarwin force-pushed the pbacondarwin/wrangler-oauth-device-flow branch from 6318f88 to 24ccd5f Compare June 12, 2026 13:46

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

Open in Devin Review

Comment thread packages/workers-auth/src/device-flow.ts
Adds a new `--experimental-device` flag to `wrangler login` that uses the
OAuth 2.0 Device Authorization Grant (RFC 8628) instead of the existing
localhost callback flow.

The new flow:
- prints the verification URL and user code to the terminal,
- attempts to open the verification URL in the default browser,
- prints a QR code of the verification URL,
- polls the token endpoint with grant_type=device_code until the user
  approves the request, denies it, or the device code expires,
- caps polling at 5 minutes to limit any leaked-user-code abuse window.

Useful in containers, remote SSH sessions, and Codespaces where the OAuth
provider cannot reach a callback server on localhost:8976.

`--callback-host` and `--callback-port` are rejected when
`--experimental-device` is set, since the device flow has no local
callback server.

The device-flow primitives live in `@cloudflare/workers-auth` (exposed via
the existing `createOAuthFlow(...)` API as a `device` login option), so
other Cloudflare CLIs that consume the package get the flow for free. The
QR renderer is injected through the OAuth flow context, mirroring the
existing `generateAuthUrl` / `generateRandomState` test-injection seam.

The flag is gated as experimental and is inert until the supporting
server-side work ships (AUTHN-216 / AUTHN-217 / AUTHN-218).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Untriaged

Development

Successfully merging this pull request may close these issues.

Failed to wrangler login in WSL

2 participants