Skip to content

Implement SEP-990 Enterprise Managed OAuth#1593

Open
sagar-okta wants to merge 3 commits intomodelcontextprotocol:mainfrom
sagar-okta:feature/sep-990
Open

Implement SEP-990 Enterprise Managed OAuth#1593
sagar-okta wants to merge 3 commits intomodelcontextprotocol:mainfrom
sagar-okta:feature/sep-990

Conversation

@sagar-okta
Copy link

@sagar-okta sagar-okta commented Feb 26, 2026

This PR implements SEP-990 Enterprise Managed Authorization using a provider-based approach with RFC 8693 Token Exchange and RFC 7523 JWT Bearer flows. This enables secure cross-app authentication for MCP clients in enterprise environments where users authenticate with an enterprise IdP.

Related: #1090

Motivation and Context

Enterprise environments often require OAuth flows where users authenticate with a centralized identity provider (IdP), and applications need to securely access protected resources on behalf of those users without storing credentials. SEP-990 addresses this by implementing:

  • Token Exchange (RFC 8693): Exchanges a user's ID token from an enterprise IdP for a JWT Authorization Grant (JAG)
  • JWT Bearer Grant (RFC 7523): Exchanges the JAG for an access token to access MCP server resources
  • OAuth Discovery (RFC 9728): Automatically discovers authorization server metadata for both IdP and MCP servers

This change is needed to support enterprise customers who need to integrate MCP clients into their existing OAuth infrastructure securely, following the same provider pattern as ClientCredentialsProvider and PrivateKeyJwtProvider.

Implementation Approach

Following PR review feedback, this implementation uses a provider-based approach instead of middleware:

Layer 2 - Utility Functions (crossAppAccess.ts):

  • requestJwtAuthorizationGrant() - RFC 8693 token exchange at IdP
  • discoverAndRequestJwtAuthGrant() - Discovery + token exchange
  • exchangeJwtAuthGrant() - RFC 7523 JWT bearer grant at MCP server

Layer 3 - Provider Class (authExtensions.ts):

  • CrossAppAccessProvider - Implements OAuthClientProvider interface
  • Uses assertion callback pattern for flexible IdP integration
  • Automatically handles OAuth discovery and token exchange flow

Core Integration (auth.ts):

  • Enhanced OAuthClientProvider interface with optional URL storage methods
  • Modified auth() to save discovered URLs for providers that need them

How Has This Been Tested?

Added comprehensive test coverage (40 tests total):

crossAppAccess.test.ts (12 tests):

  • Successful token exchange flows
  • OAuth discovery integration
  • Error handling (400, 401, 500 responses)
  • OAuth error responses (invalid_request, invalid_client, invalid_grant, etc.)
  • Token type validation
  • Request parameter encoding

authExtensions.test.ts (16 new tests):

  • End-to-end provider authentication flow
  • Assertion callback with context (authorizationServerUrl, resourceUrl, scope, fetchFn)
  • Custom fetch function handling
  • Authorization server and resource URL storage/retrieval
  • Client metadata configuration
  • Error handling for missing URLs and assertion failures

Updated client.md:

  • Removed old middleware-based documentation
  • Added new provider-based usage examples
  • Positioned in Authentication section alongside other providers

Breaking Changes

No breaking changes - This is an additive feature:

  • New CrossAppAccessProvider class (does not modify existing providers)
  • Optional methods added to OAuthClientProvider interface (backward compatible)
  • Existing auth flows remain unchanged
  • Old middleware approach completely removed (was never released)

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally (40/40 tests passing)
  • I have added appropriate error handling
  • I have added or updated documentation as needed
  • Code is properly formatted (ESLint + Prettier)
  • No unused imports or TypeScript errors

Additional Context

Implementation Details:

New Files:

  • crossAppAccess.ts (230 lines) - Layer 2 utilities for token exchange
  • crossAppAccess.test.ts (12 test cases)

Modified Files:

  • authExtensions.ts - Added CrossAppAccessProvider class (~80 lines)
  • auth.ts - Enhanced OAuthClientProvider interface with optional URL storage methods
  • middleware.ts - Removed old withCrossAppAccess middleware
  • index.ts - Added export for crossAppAccess module
  • authExtensions.test.ts - Added 16 provider tests
  • client.md - Updated documentation with provider-based examples

Key Features:

  • Assertion callback pattern allows flexible IdP integration
  • Automatic OAuth metadata discovery for both IdP and MCP servers
  • Comprehensive error handling with OAuth-specific error parsing
  • Consistent with existing provider patterns (ClientCredentialsProvider, PrivateKeyJwtProvider)
  • Supports custom fetch functions for middleware composition
  • Scope passing through the entire flow

Dependencies:

  • Uses existing qs dependency for proper OAuth parameter encoding
  • No new dependencies added

@sagar-okta sagar-okta requested a review from a team as a code owner February 26, 2026 06:15
@changeset-bot
Copy link

changeset-bot bot commented Feb 26, 2026

⚠️ No Changeset found

Latest commit: b3d31ff

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 26, 2026

Open in StackBlitz

@modelcontextprotocol/client

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

@modelcontextprotocol/server

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

@modelcontextprotocol/express

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

@modelcontextprotocol/hono

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

@modelcontextprotocol/node

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

commit: b3d31ff

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