Skip to content

Conversation

stephaneberle9
Copy link
Contributor

Description

This PR implements native Keycloak OAuth support for FastMCP, enabling enterprise-grade authentication for organizations using Keycloak identity and access management infrastructure. The implementation provides a complete authentication provider that handles Keycloak User Realms with robust JWT token validation and Dynamic Client Registration (DCR) support. This contribution also significantly simplifies local development by providing a Docker-based Keycloak setup that allows developers to test OAuth flows instantly without external dependencies.

Contributors Checklist

Review Checklist

  • I have self-reviewed my changes
  • My Pull Request is ready for review

- Add AWSCognitoProvider class extending OAuthProxy for Cognito User Pools
- Implement JWT token verification using authlib with JWKS validation
- Support automatic domain construction from prefix and region
- Add comprehensive error handling and debug logging
- Include working example server and client with documentation
- Follow FastMCP authentication provider patterns and standards
- Use existing dependencies (authlib, httpx) without adding new ones
- Add test_aws.py with full test coverage for AWSCognitoProvider
- Test provider initialization, configuration, error handling, and Cognito-specific features (domain construction, scopes, claims)
- Cover error scenarios: invalid tokens, expired tokens, wrong issuer
- Use AsyncMock/MagicMock for comprehensive AWS Cognito API simulation
…stMCP:

- Step-by-step setup guide reflecting AWS Cognito's streamlined UI
- Traditional web application configuration for server-side auth
- JWT token validation and user claims handling
- Environment variable configuration options
- Code examples for server setup and client testing
- Enterprise features including SSO, MFA, and role-based access
- Add get_user_profile tool to server for retrieving authenticated user data
- Update client example to demonstrate profile retrieval functionality
- Fix mistaken documentation examples and improve error handling and data display
- Add commented redirect_path configuration option for better awareness
Remove email, name, and other profile claims from AccessToken as these
are not included in AWS Cognito access tokens per documentation. Keep
only sub, username, and cognito:groups which are the standard claims
available in access tokens for authorization purposes. Update examples
and docs.
Replace duplicate JWT verification logic in AWSCognitoTokenVerifier by
extending JWTVerifier instead of TokenVerifier. This eliminates ~150
lines of duplicated code including JWKS fetching, caching, token
validation, and JWT decoding logic.

Key changes:
- AWSCognitoTokenVerifier now extends JWTVerifier for core JWT operations
- Removed duplicate JWKS/JWT logic and dependencies (httpx, authlib.jose)
- Simplified constructor to configure parent with Cognito URLs and RS256
- Override verify_token() to filter claims to Cognito-specific subset
- Updated tests to work with new inheritance structure

Benefits:
- Eliminates code duplication between JWT providers
- Leverages existing JWT infrastructure and improvements
- Maintains backward compatibility while reducing complexity
- Cleaner separation of JWT verification vs Cognito-specific logic
The timeout_seconds parameter is no longer needed after refactoring
AWSCognitoTokenVerifier to extend JWTVerifier. HTTP timeouts for JWKS
requests are now handled by the parent JWTVerifier class.
…ain_prefix

This change modernizes the AWS Cognito provider by:
- Switching from OAuthProxy to OIDCProxy with automatic OIDC Discovery
- Removing the domain_prefix parameter and related configuration
- Updating get_token_verifier to instantiate AWSCognitoTokenVerifier directly
- Simplifying provider initialization by using Cognito's well-known OIDC endpoints
- Updating documentation and examples to reflect the streamlined configuration
Implement KeycloakAuthProvider that extends RemoteAuthProvider to support
Keycloak integration using OAuth 2.1/OpenID Connect with Dynamic Client
Registration (DCR). The provider automatically discovers OIDC endpoints
and forwards authorization server metadata to enable seamless client
authentication.

Key features:
- Automatic OIDC endpoint discovery from Keycloak realm
- JWT token verification with JWKS support
- Authorization server metadata forwarding for DCR
- Configurable scope requirements and custom token verifiers
- Environment variable configuration support

Includes comprehensive example with:
- Docker Compose setup with Keycloak 26.2
- Pre-configured test realm with client and user
- Complete server and client demonstration
- Automated setup script with health checks
- Detailed documentation and troubleshooting guide
…ications in client registration responses for Keycloak OAuth provider

Enhances the existing Keycloak authentication provider with automatic scope management
to eliminate client-side scope configuration requirements.

Key improvements:
- Server-side injection of required scopes into client registration and authorization requests
- Automatic FastMCP compatibility modifications of Keycloak client registration responses
- Updated Keycloak test realm configuration to resolve trusted host and duplicate client scope issues
- Enhanced example with proper scope handling and user claim access
Remove hardcoded fastmcp-client configuration and add DCR policy and profile to enable
dynamic client registration. This allows clients to register automatically at runtime rather
than requiring pre-configured client entries.
Implement complete test coverage for the Keycloak authentication provider with 23 comprehensive tests (16 unit tests, 7 integration tests) covering all aspects of OAuth integration and Dynamic Client Registration (DCR).

Key Features Tested:
- Dynamic Client Registration (DCR) with scope injection
- FastMCP compatibility modifications (auth method, response types)
- OAuth proxy architecture for CORS prevention
- Server-configured required scopes automatic injection
- JWT token verification with JWKS integration
- Complete inheritance from RemoteAuthProvider

All tests pass with zero warnings and verify the provider is production-ready for both Docker development environments and enterprise Keycloak deployments.
Docker setup

- Upgrade Keycloak image from 26.2 to 26.3
- Rename realm-export.json to realm-fastmcp.json for clarity
- Simplify docker-compose.yml configuration by removing unnecesary
  settings and relying on defaults instead
- Add Docker network gateway IP (172.17.0.1) to trusted hosts for
  improved container networking
- Update realm configuration to use cleaner policy and profile names
Keycloak restart in auth example

- Include detailed comments explaining the Keycloak
   restart scenario and the "We are sorry... Client
  not found" error that may show up
- Add a code snippet enabling users to easily clear their
  OAuth cache when running their client in such situations
- Create complete Keycloak integration guide with step-by-step
  setup instructions
- Include Docker setup examples and realm configuration import
  process
- Document Dynamic Client Registration (DCR) configuration and
  troubleshooting
- Provide environment variable configuration options and examples
- Include advanced configuration scenarios with custom token
  verifiers
- Add troubleshooting section for resolution of common
  "Client not found" error in Keycloak restart scenarios
- Update docs navigation to include Keycloak integration
@marvin-context-protocol marvin-context-protocol bot added enhancement Improvement to existing functionality. For issues and smaller PR improvements. server Related to FastMCP server implementation or server-side functionality. auth Related to authentication (Bearer, JWT, OAuth, WorkOS) for client or server. labels Sep 27, 2025
Copy link
Owner

@jlowin jlowin left a comment

Choose a reason for hiding this comment

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

It feels like there's way too much going on in this PR. Did an LLM author this?

  • The example should be a minimal server/client pair like all other auth providers. There should definitely not be a docker-compose file.
  • keycloak.py seems to reimplement our oauthproxy AND oidcproxy while still claiming (in the linked issue) to natively support DCR? Ideally this would be a minor amount of configuration against one of FastMCP's establish auth classes.

Split the verbose Keycloak README.md to improve clarity and match the
simplicity of other auth provider examples:

- Move Keycloak setup details to keycloak/README.md
- Simplify main README.md with two clear options:
  - Option A: Local Keycloak instance (automatic realm import)
  - Option B: Existing Keycloak instance (manual realm import)
- Reorganize Docker files into keycloak/ subdirectory
- Rename setup.sh to start-keycloak.sh for clarity
- Remove Python venv setup from start script (focus on Keycloak only)
- Add prerequisites, troubleshooting, and configuration details to
  keycloak/README.md
- Clarify that realm is auto-imported for local Docker setup
- Add note about restarting Keycloak after configuration changes
Remove unused mcp_endpoint parameter from get_routes() method to match
parent RemoteAuthProvider signature. The parameter was not used and
caused test failures with TypeError when calling super().get_routes().

Changes:
- Remove mcp_endpoint parameter from get_routes() signature
- Update super().get_routes() call to only pass mcp_path
- Remove unused typing.Any import
- Update docstring to reflect parameter removal

Fixes 9 failing tests in:
- tests/integration_tests/auth/test_keycloak_provider_integration.py
- tests/server/auth/providers/test_keycloak.py
@stephaneberle9
Copy link
Contributor Author

stephaneberle9 commented Oct 6, 2025

It feels like there's way too much going on in this PR. Did an LLM author this?

I do use Claude Code, yes, but not "blindly". Means that I don't vibe-code my changes but meticulously review and iteratively adapt whatever it is suggesting. That said, I must admit that I'd missed to do that with the README.md of the new keycloak auth example which most probably has caused some degree of confusion. Sorry for that! I've fixed this as per 715aa92 now.

The example should be a minimal server/client pair like all other auth providers. There should definitely not be a docker-compose file.

Keycloak is a leading identity provider that has a big extra advantage: it can very easily be run locally using Docker or Docker Compose. Therefore, it is frequently used as a substitute for production IDPs to create fully self-contained local dev setups. The intent of this contribution is to enable both easy FastMCP auth support for productive Keycloak instances and use of Keycloak as IDP in local FastMCP dev setups.

That said, I fully understand that the presence of the Docker Compose configuration and scripts adds some extra complexity which compromises the idea of having simplistic examples. I therefore have reorganized the Keycloak example in the following way:

  • All the Docker Compose stuff, the start script and an extra README.md file have been moved into the keycloak subfolder
  • The example folder itself is now very similar to the other examples and basically only contains the server.py and client.py files
  • The README.md file in this folder is also very compact now. It clearly indicates that there two options: running the example with an already existing Keycloak instance or creating a local Keycloak dev instance with Docker Compose. For the details regarding how to proceed in the second case the user is referred to more detailed instructions in the README.md located in the keycloak subfolder.

keycloak.py seems to reimplement our oauthproxy AND oidcproxy while still claiming (in the linked issue) to natively support DCR? Ideally this would be a minor amount of configuration against one of FastMCP's establish auth classes.

No, the KeycloakAuthProvider is clearly NOT a reimplementation of OAuthProxy/OIDCProxy. It's a fundamentally different architecture:

OAuthProxy/OIDCProxy: Full OAuth authorization server that translates between non-DCR IDPs and DCR-expecting clients
KeycloakAuthProvider: Lightweight metadata proxy that exposes Keycloak's native DCR with minimal request/response modifications

What the KeycloakAuthProvider does:

  • Extends RemoteAuthProvider (NOT OAuthProvider)
  • Does NOT implement the OAuth flow
  • Does NOT store tokens, codes, or manage OAuth state
  • Only proxies 3 HTTP endpoints for metadata/request modifications:
    • /.well-known/oauth-authorization-server - Metadata discovery
    • /register - DCR with scope injection
    • /authorize - Authorization with scope injection

Key proofs we're NOT reimplementing::

  • KeycloakAuthProvider doesn't require any client ID or client secret at instantiation - because it doesn't need to authenticate with Keycloak on behalf of clients. In contrast, OAuthProxy/OIDCProxy require upstream_client_id and upstream_client_secret because they act as a full OAuth client to the upstream provider.
  • KeycloakAuthProvider reuses OIDCConfiguration from oidc_proxy.py instead of reimplementing OIDC discovery - it's leveraging existing FastMCP infrastructure, not duplicating it.

The fact that the Keycloak auth provider proxies some HTTP requests does not mean it reimplements OAuth flow logic. This is exactly the "minor amount of configuration against one of FastMCP's established auth classes" - it's built on RemoteAuthProvider and adds only the minimal proxying required to bridge Keycloak's native DCR with MCP client expectations.

The Keycloak auth provider does include OIDC discovery because Keycloak supports it natively, and it would be unfortunate to force users to manually configure the authorization, token, and other endpoints individually instead. However, this has been achieved by reusing, not duplicating, existing logic from OIDCConfiguration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auth Related to authentication (Bearer, JWT, OAuth, WorkOS) for client or server. enhancement Improvement to existing functionality. For issues and smaller PR improvements. server Related to FastMCP server implementation or server-side functionality.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Keycloak OAuth Authentication Provider leveraging Dynamic Client Registration (DCR)

2 participants