Skip to content

Handle OAuth provider and authorize route exceptions - #638

Merged
kentcdodds merged 3 commits into
mainfrom
cursor/fix-oauth-provider-exceptions-634a
Jul 6, 2026
Merged

kentcdodds merged 3 commits into
mainfrom
cursor/fix-oauth-provider-exceptions-634a

Conversation

@kentcdodds

@kentcdodds kentcdodds commented Jul 6, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Add error boundaries for OAuth provider-owned routes (/oauth/token, /oauth/register, discovery/API routes) so provider exceptions return OAuth JSON errors instead of Worker 1101s.
  • Add a delegated /oauth/authorize and /oauth/authorize-info boundary so Kody captures route exceptions and returns recoverable OAuth responses.
  • Expand Claude-shaped coverage to include dynamic registration -> authorize -> token exchange plus malformed provider and authorize request failures, including Sentry capture for malformed token-client failures.

Research notes

  • Production analytics for the retry window showed successful /oauth/register requests followed by three /oauth/authorize 500s at 03:54-03:55 UTC.
  • Sentry had no matching Kody issue for that window, consistent with exceptions escaping before app-level capture.
  • Cloudflare Log Explorer request-level traces are not enabled for this account/token, so GraphQL HTTP analytics was the available production evidence.
  • Provider source confirms isValidRedirectUri(..., clientInfo.redirectUris) can still throw on malformed client records in provider-owned token paths.

Testing

  • npx vitest run --project workers-unit packages/worker/src/oauth-handlers.workers.test.ts -t "delegated authorize|provider-owned|dynamic registration|Claude-shaped"
  • npx vitest run --project workers-unit packages/worker/src/oauth-handlers.workers.test.ts
  • npm run test -- packages/worker/src/oauth-handlers.workers.test.ts
  • npm run format:check
  • npm run lint
  • npm run typecheck
  • npm run validate
  • Pre-push hook: npm run test:push
  • GitHub checks: Validate, Deploy Preview Resources, CodeRabbit, and Cursor Bugbot
System recap β€” extends existing primitives (medium risk)

Mode: recap Β· Base: main @ 82c720b2 Β· Head: 386c3f4c

Classification: extends β€” changes mcp-oauth error handling for provider-owned and delegated authorize routes.

Primitives touched

Primitive Group Impact
mcp-oauth auth extends β€” converts uncaught OAuth route exceptions into OAuth responses and captures provider-owned failures
app-ui surfaces composes β€” browser authorize failures get a minimal recoverable page instead of Cloudflare 1101
mcp-server surfaces composes β€” Claude MCP OAuth flow remains scoped to /mcp resource audience

System map

flowchart LR
	claude["Claude MCP client"]:::untouched --> mcpOauth["mcp-oauth"]:::extended
	mcpOauth --> appUi["app-ui"]:::touched
	mcpOauth --> mcpServer["mcp-server"]:::touched
	classDef touched fill:#1a7f37,color:#fff
	classDef extended fill:#9a6700,color:#fff
	classDef added fill:#cf222e,color:#fff
	classDef untouched fill:#57606a,color:#fff
Loading

Change flow

flowchart TD
	register["/oauth/register"] --> authorize["/oauth/authorize"]
	authorize -->|success| token["/oauth/token"]
	authorize -->|route exception| authError["OAuth error page or JSON"]
	token -->|provider exception| tokenError["OAuth JSON error + Sentry"]
	authError --> no1101["no Worker 1101"]
	tokenError --> no1101
Loading

Before / after

Before After
Provider token/register exceptions and delegated authorize exceptions could escape as Worker 1101. OAuth routes return OAuth-shaped JSON or a minimal authorize error page and unexpected failures are reported to Sentry.
Tests covered only valid and malformed authorize GET records. Tests cover fresh Claude dynamic registration, token exchange, provider-route exceptions with Sentry capture, and delegated authorize exceptions.
Open in WebΒ Open in CursorΒ 

Summary by CodeRabbit

  • New Features

    • Added OAuth authorization server discovery support at /.well-known/oauth-authorization-server.
    • Standardized OAuth error responses across JSON, HTML, and redirect formats for authorization flows.
  • Bug Fixes

    • Prevented exceptions from bubbling out of OAuth authorize and provider-owned routes by returning consistent, mapped OAuth error payloads.
    • Improved handling for specific malformed-client and client-registration error cases, including Sentry reporting.
  • Tests

    • Expanded end-to-end OAuth coverage (PKCE/S256, registration, approval, code extraction, token exchange).
    • Added new provider-owned and delegated authorization error-path tests with Sentry assertions.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026 •

Copy link
Copy Markdown

Review Change Stack

πŸ“ Walkthrough

Walkthrough

This PR adds centralized exception handling for OAuth authorization and token flows in the worker. It introduces error-mapping helpers in oauth-handlers.ts and index.ts to produce standardized JSON/HTML error responses, wraps route handlers in try/catch with Sentry capture, and expands test coverage with new worker test helpers and end-to-end/error-path tests.

Changes

OAuth Exception Handling

Layer / File(s) Summary
Error response helpers
packages/worker/src/oauth-handlers.ts
Adds the discovery path, an HTML error response helper for authorization failures, and an exported handleAuthorizeRouteException function that returns JSON, redirect, or HTML responses depending on request type and path.
Route and fetch error wiring
packages/worker/src/index.ts
Imports the new exception handler, wraps /oauth/authorize, /oauth/authorize-info, and oauthProvider.fetch calls in try/catch with Sentry capture, and adds helpers to detect OAuth-owned paths, malformed-client errors, and build standardized JSON error responses.
Worker test helpers and coverage
packages/worker/src/oauth-handlers.workers.test.ts
Refactors workerFetch to accept a custom environment, adds createS256CodeChallenge, createSha256Hex, and seedWorkerUser helpers, and adds end-to-end and error-path tests for registration, authorization, token exchange, and exception responses.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Worker as index.ts fetch
  participant OAuthProvider
  participant Sentry
  participant Handlers as oauth-handlers.ts

  Client->>Worker: request /oauth/authorize or /oauth/token
  Worker->>OAuthProvider: forward request
  OAuthProvider-->>Worker: throws error
  Worker->>Worker: check isOAuthOwnedPath / isMalformedOAuthClientException
  alt not OAuth-owned
    Worker-->>Client: rethrow error
  else OAuth-owned
    Worker->>Sentry: captureException
    Worker->>Handlers: handleAuthorizeRouteException / createOAuthProviderExceptionResponse
    Handlers-->>Worker: standardized error Response
    Worker-->>Client: JSON/redirect/HTML error response
  end
Loading

Possibly related PRs

  • kentcdodds/kody#169: Overlaps in /oauth/authorize-info error handling and invalid-client-mismatch reset logic within oauth-handlers.ts.
  • kentcdodds/kody#582: Both changes touch OAuth authorization handling and authorize-route failure behavior in packages/worker/src/oauth-handlers.ts.
πŸš₯ Pre-merge checks | βœ… 5
βœ… Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage βœ… Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Description Check βœ… Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check βœ… Passed The title clearly summarizes the main change: adding exception handling for OAuth provider routes and authorize route flows.
✨ Finishing Touches
πŸ“ Generate docstrings
  • Create stacked PR
  • Commit on current branch
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/fix-oauth-provider-exceptions-634a

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.

@kentcdodds
kentcdodds marked this pull request as ready for review July 6, 2026 04:27
@github-actions

github-actions Bot commented Jul 6, 2026 •

Copy link
Copy Markdown
Contributor

πŸ”Ž Preview deployed: https://kody-pr-638.kentcdodds.workers.dev

Worker: kody-pr-638
D1: kody-pr-638-db
KV: kody-pr-638-oauth-kv

Mocks:

@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

🧹 Nitpick comments (2)
packages/worker/src/index.ts (2)

407-416: πŸ“ Maintainability & Code Quality | πŸ”΅ Trivial | ⚑ Quick win

Extract the OAuth discovery path into a shared constant

'/.well-known/oauth-authorization-server' is hardcoded here while the adjacent paths come from shared constants. Moving it into the same shared source would avoid drift if this path changes.

πŸ€– Prompt for 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.

In `@packages/worker/src/index.ts` around lines 407 - 416, The OAuth discovery
route is hardcoded inside isOAuthProviderOwnedPath while the neighboring checks
already use shared constants. Move '/.well-known/oauth-authorization-server'
into the same shared path source as oauthPaths and
protectedResourceMetadataPath, then update isOAuthProviderOwnedPath to reference
that constant so all OAuth-owned paths stay centralized and consistent.

418-424: πŸ“ Maintainability & Code Quality | πŸ”΅ Trivial | πŸ’€ Low value

Document this version-specific OAuth workaround isMalformedOAuthClientException relies on a raw TypeError message from @cloudflare/workers-oauth-provider@0.4.0, so an upstream fix or wording change will silently change token failures back to server_error. Add a short comment/link to the upstream bug here so the coupling is explicit.

πŸ€– Prompt for 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.

In `@packages/worker/src/index.ts` around lines 418 - 424, Document the
version-specific OAuth workaround in isMalformedOAuthClientException by adding a
short comment and upstream bug reference near the message check so the
dependency on `@cloudflare/workers-oauth-provider`@0.4.0 is explicit. Keep the
existing pathname/oauthPaths.token and TypeError message guard, but annotate
that this raw error text is intentional and tied to the upstream issue so future
wording changes are easy to spot.
πŸ€– 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 `@packages/worker/src/index.ts`:
- Around line 513-521: The try/catch in the worker request handler still
suppresses Sentry for the recognized malformed-client path, which removes the
telemetry this PR is meant to restore. Update the catch block in the request
flow around oauthProvider.fetch so that Sentry.captureException is still called
for isMalformedOAuthClientException cases, while keeping
createOAuthProviderExceptionResponse(error, url.pathname) unchanged for the
client response; only preserve the rethrow for non-owned paths.

---

Nitpick comments:
In `@packages/worker/src/index.ts`:
- Around line 407-416: The OAuth discovery route is hardcoded inside
isOAuthProviderOwnedPath while the neighboring checks already use shared
constants. Move '/.well-known/oauth-authorization-server' into the same shared
path source as oauthPaths and protectedResourceMetadataPath, then update
isOAuthProviderOwnedPath to reference that constant so all OAuth-owned paths
stay centralized and consistent.
- Around line 418-424: Document the version-specific OAuth workaround in
isMalformedOAuthClientException by adding a short comment and upstream bug
reference near the message check so the dependency on
`@cloudflare/workers-oauth-provider`@0.4.0 is explicit. Keep the existing
pathname/oauthPaths.token and TypeError message guard, but annotate that this
raw error text is intentional and tied to the upstream issue so future wording
changes are easy to spot.
πŸͺ„ 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: a3cd90b0-a8a6-4878-b931-c94d2ef2014e

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 82c720b and 5fbc1d8.

πŸ“’ Files selected for processing (3)
  • packages/worker/src/index.ts
  • packages/worker/src/oauth-handlers.ts
  • packages/worker/src/oauth-handlers.workers.test.ts

Comment thread packages/worker/src/index.ts
@kentcdodds
kentcdodds merged commit 108d8b3 into main Jul 6, 2026
5 checks passed
@kentcdodds
kentcdodds deleted the cursor/fix-oauth-provider-exceptions-634a branch July 6, 2026 04:47
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.

2 participants