Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Proxy OAuth Server Provider #159

Open
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

allenzhou101
Copy link

@allenzhou101 allenzhou101 commented Feb 25, 2025

Introduces a new ProxyOAuthServerProvider class that enables proxying OAuth operations to an upstream OAuth server, allowing delegation of OAuth flows while maintaining our interface contract.

Motivation and Context

In many deployment scenarios, we need to integrate with existing OAuth infrastructure (like corporate identity providers or third-party auth services) rather than implementing OAuth flows directly. This proxy implementation provides a clean abstraction layer that allows applications to delegate OAuth operations to an upstream server while maintaining a consistent interface to plug into other parts of the MCP sdk (eg. routing).

How Has This Been Tested?

Using Descope as the external/upstream OAuth IdP and MCP Inspector as the client, the below cases were tested:

  • OAuth endpoint proxying only
  • Combination of OAuth endpoint and overriding (eg. only proxying the token endpoint and explicitly defining authorize)

Breaking Changes

None

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
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Considerations

  • abstract class instead of class for ProxyOAuthServerProvider, but the latter is slightly easier dx-wise
  • separate mcp auth router function for proxying but probably better to maintain consistent proxy functionality like rate limits and leverage overlap
  • could implement token verification via JWKs from metadata and and client getting via /register out of the box later on
  • also open to different naming like passthrough proxy instead

Usage

const app = express();

const proxyProvider = new ProxyOAuthServerProvider({
    endpoints: {
        authorizationUrl: "https://auth.external.com/oauth2/v1/authorize",
        tokenUrl: "https://auth.external.com/oauth2/v1/token",
        revocationUrl: "https://auth.external.com/oauth2/v1/revoke",
    },
    verifyAccessToken: async (token) => {
        return {
            token,
            clientId: "123",
            scopes: ["openid", "email", "profile"],
        }
    },
    getClient: async (client_id) => {
        return {
            client_id,
            redirect_uris: ["http://localhost:3000/callback"],
        }
    }
})

app.use(mcpAuthRouter({
    provider: proxyProvider,
    issuerUrl: new URL("http://auth.external.com"),
    baseUrl: new URL("http://mcp.example.com"),
    serviceDocumentationUrl: new URL("https://docs.example.com/"),
}))

We could also totally remove the getClient required parameter from the ProxyOAuthServerProvider and add a boolean to the OAuthServerProvider to skip local redirect uri validation and whatever the getClient function is used for to rely on the upstream server. This would simplify implementation while allowing devs to easily override and define to handle validation logic in the server if desired.

@allenzhou101 allenzhou101 marked this pull request as draft February 25, 2025 01:28
@allenzhou101 allenzhou101 marked this pull request as ready for review February 25, 2025 04:18
@allenzhou101 allenzhou101 force-pushed the server-authorization-proxy branch from da8bb7e to 8d7b387 Compare February 27, 2025 21:35
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