Skip to content

feat(client): add getAuthorizationCode() to OAuthClientProvider for headless OAuth flows#1662

Open
rechedev9 wants to merge 4 commits intomodelcontextprotocol:mainfrom
rechedev9:fix/oauth-retry-middleware-1370
Open

feat(client): add getAuthorizationCode() to OAuthClientProvider for headless OAuth flows#1662
rechedev9 wants to merge 4 commits intomodelcontextprotocol:mainfrom
rechedev9:fix/oauth-retry-middleware-1370

Conversation

@rechedev9
Copy link
Copy Markdown

Summary

Resolves #1370.

The conformance test helpers contained a TODO noting that the OAuth retry logic (handling REDIRECT results and completing the code exchange inline) should be moved into the SDK itself. This PR does exactly that.

  • Add optional getAuthorizationCode?(): string | Promise<string> method to the OAuthClientProvider interface
  • Update withOAuth middleware to automatically complete the authorization code exchange when the provider implements getAuthorizationCode() after an auth REDIRECT — no manual intervention required
  • Handle 403 responses the same as 401 in withOAuth (a 403 can indicate the server requires a broader scope / upscoping)
  • Rename ConformanceOAuthProvider.getAuthCode()getAuthorizationCode() to implement the updated interface
  • Update withOAuthRetry conformance helper to use the new method name and remove the TODO comment

Breaking Changes

  • None. getAuthorizationCode() is an optional method on OAuthClientProvider. Existing providers without it continue to work — on REDIRECT, withOAuth falls back to throwing UnauthorizedError as before.

Test plan

  • Added test: should retry request after successful auth on 403 response
  • Added test: should throw UnauthorizedError on persistent 403 after re-auth
  • Added test: should complete auth code flow when provider implements getAuthorizationCode
  • Added test: should throw UnauthorizedError when auth returns REDIRECT and provider has no getAuthorizationCode
  • All 261 existing middleware tests pass
  • pnpm typecheck:all passes

@rechedev9 rechedev9 requested a review from a team as a code owner March 11, 2026 18:28
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 11, 2026

🦋 Changeset detected

Latest commit: eac311a

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

This PR includes changesets to release 1 package
Name Type
@modelcontextprotocol/client Minor

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

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Mar 11, 2026

Open in StackBlitz

@modelcontextprotocol/client

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/client@1662

@modelcontextprotocol/server

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/server@1662

@modelcontextprotocol/express

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/express@1662

@modelcontextprotocol/hono

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/hono@1662

@modelcontextprotocol/node

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/node@1662

commit: eac311a

…eadless OAuth flows

- Add optional `getAuthorizationCode()` method to `OAuthClientProvider` interface
- Update `withOAuth` middleware to automatically complete the authorization code
  exchange when the provider implements `getAuthorizationCode()` after a REDIRECT
- Handle 403 responses the same as 401 in `withOAuth` (upscoping)
- Update conformance `ConformanceOAuthProvider` to implement `getAuthorizationCode()`
- Update conformance `withOAuthRetry` to use the new method name and remove TODO

Closes modelcontextprotocol#1370
@rechedev9 rechedev9 force-pushed the fix/oauth-retry-middleware-1370 branch from 6b9cb53 to 57c7c85 Compare March 11, 2026 18:31
@felixweinberger
Copy link
Copy Markdown
Contributor

@claude review

Copy link
Copy Markdown

@claude claude bot left a comment

Choose a reason for hiding this comment

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

No bugs found, but this PR modifies OAuth authentication middleware (handling 403 as 401, adding getAuthorizationCode to the public OAuthClientProvider interface) — worth a human look given the security sensitivity and behavioral change.

Extended reasoning...

Overview

This PR adds an optional getAuthorizationCode() method to the OAuthClientProvider interface and updates withOAuth middleware to use it for automatic authorization code exchange. It also changes withOAuth to treat HTTP 403 responses the same as 401 (triggering re-authentication), and renames getAuthCode to getAuthorizationCode in the conformance test helpers.

Security risks

The changes are in OAuth authentication middleware — a security-sensitive area. The 403-as-401 change broadens the set of responses that trigger re-authentication flows, which could have subtle implications: a legitimate 403 (e.g., the user genuinely lacks permission) would now trigger a full re-auth cycle instead of being returned to the caller. This deserves human consideration for whether the behavior is appropriate in all cases.

Level of scrutiny

This warrants careful human review. It modifies a public TypeScript interface (OAuthClientProvider), changes middleware behavior for all consumers of withOAuth, and touches auth-critical code paths. The implementation looks clean and tests cover the new behaviors well, but the design decisions (especially 403 handling) should be validated by a maintainer.

Other factors

The PR includes 4 well-structured new tests. The changeset is correctly marked as a minor version bump. The conformance helper changes are consistent with the SDK changes. No existing tests appear to be broken. The author field shows as Unknown, and no human reviewers have weighed in yet.

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.

Incorporate OAuth retry logic from conformance helpers into SDK

2 participants