Multi-Provider Identity Provider (IdP) Support¶
Version: 1.0 Last Updated: 2026-01-18
Related Documentation¶
- Authentication Design - Auth flows for human users, programmatic access, and M2M workloads
- Authentication & Authorization Guide - Operational guide with setup instructions
- Microsoft Entra ID Integration - Entra ID-specific setup and configuration
Overview¶
The MCP Gateway Registry supports multiple identity providers (IdPs) through a pluggable architecture. This design enables organizations to use their existing enterprise identity infrastructure (Keycloak, Microsoft Entra ID) for authentication and authorization.
Architecture¶
High-Level Component Diagram¶
+------------------+ +------------------+ +------------------+
| | | | | |
| Registry UI | | CLI Tools | | AI Agents |
| (Frontend) | | (registry_mgmt) | | (M2M Clients) |
| | | | | |
+--------+---------+ +--------+---------+ +--------+---------+
| | |
| HTTP + JWT Token | HTTP + JWT Token |
| | |
v v v
+--------+------------------------+------------------------+---------+
| |
| NGINX Gateway |
| (auth_request /validate) |
| |
+--------+-----------------------------------------------------------+
|
| /validate
v
+--------+-----------------------------------------------------------+
| |
| Auth Server |
| |
| +----------------+ +------------------+ +----------------+ |
| | | | | | | |
| | AuthProvider | | AuthProvider | | AuthProvider | |
| | Factory +--->+ Protocol +--->+ Implementations| |
| | | | (Base Class) | | | |
| +----------------+ +------------------+ +----------------+ |
| | |
| +----------------+---------+ |
| | | |
| v v |
| +------+------+ +------+------+ |
| | | | | |
| | Keycloak | | Entra ID | |
| | Provider | | Provider | |
| | | | | |
| +-------------+ +-------------+ |
| |
+--------------------------------------------------------------------+
|
| Group-to-Scope Mapping
v
+--------+-----------------------------------------------------------+
| |
| MongoDB-CE / Amazon DocumentDB |
| |
| +---------------------------+ +---------------------------+ |
| | mcp_scopes_default | | mcp_servers_default | |
| | | | | |
| | - scope definitions | | - server configurations | |
| | - group_mappings | | - tool definitions | |
| | - server_access rules | | | |
| | - ui_permissions | | | |
| +---------------------------+ +---------------------------+ |
| |
+--------------------------------------------------------------------+
Provider Selection¶
The active identity provider is determined by the AUTH_PROVIDER environment variable:
Provider Factory Pattern¶
+-------------------+ +--------------------------+
| | | |
| AUTH_PROVIDER env +---->+ AuthProviderFactory |
| | | |
+-------------------+ +------------+-------------+
|
+------------------+------------------+
| |
v v
+---------+---------+ +-----------+-----------+
| | | |
| KeycloakProvider | | EntraIdProvider |
| | | |
| - OIDC endpoints | | - Microsoft Graph API |
| - JWKS validation | | - JWKS validation |
| - Realm-based | | - Tenant-based |
| | | |
+-------------------+ +-----------------------+
IAM Manager Interface¶
For administrative operations (user/group CRUD), the system uses the IAM Manager abstraction:
@runtime_checkable
class IAMManager(Protocol):
"""Protocol defining the IAM manager interface."""
async def list_users(
self,
search: str | None = None,
max_results: int = 500,
include_groups: bool = True
) -> list[dict[str, Any]]: ...
async def create_human_user(
self,
username: str,
email: str,
first_name: str,
last_name: str,
groups: list[str],
password: str | None = None,
) -> dict[str, Any]: ...
async def delete_user(self, username: str) -> bool: ...
async def list_groups(self) -> list[dict[str, Any]]: ...
async def create_group(
self,
group_name: str,
description: str = ""
) -> dict[str, Any]: ...
async def delete_group(self, group_name: str) -> bool: ...
async def create_service_account(
self,
client_id: str,
groups: list[str],
description: str | None = None
) -> dict[str, Any]: ...
Implementation Classes¶
+------------------+ +------------------+
| | | |
| KeycloakIAM | | EntraIAM |
| Manager | | Manager |
| | | |
+--------+---------+ +--------+---------+
| |
| Delegates to | Delegates to
v v
+--------+---------+ +--------+---------+
| | | |
| keycloak_manager | | entra_manager |
| .py | | .py |
| | | |
| - Keycloak Admin | | - Microsoft |
| REST API | | Graph API |
| - Realm mgmt | | - App registr. |
| - Client mgmt | | - Service |
| | | principals |
+------------------+ +------------------+
Provider-Specific Details¶
Keycloak Provider¶
Authentication Flow: - Uses OIDC Authorization Code flow - Tokens issued by Keycloak realm - JWKS endpoint: {keycloak_url}/realms/{realm}/protocol/openid-connect/certs
Group Identifier in Tokens: - Group names (e.g., registry-admins, public-mcp-users) - Stored in groups claim of JWT
IAM Operations: - Uses Keycloak Admin REST API - Requires admin credentials or service account with realm-admin role
Microsoft Entra ID Provider¶
Authentication Flow: - Uses OAuth2 Authorization Code flow (users) - Uses OAuth2 Client Credentials flow (M2M) - Tokens issued by Microsoft STS - JWKS endpoint: https://login.microsoftonline.com/{tenant_id}/discovery/v2.0/keys
Group Identifier in Tokens: - Group Object IDs (GUIDs) like 5f605d68-06bc-4208-b992-bb378eee12c5 - Stored in groups claim of JWT - Object IDs must be mapped to scope names in MongoDB
IAM Operations: - Uses Microsoft Graph API - Requires App Registration with appropriate permissions: - Application.ReadWrite.All - Directory.ReadWrite.All - Group.ReadWrite.All - User.ReadWrite.All
Group-to-Scope Mapping¶
The mapping between IdP groups and registry scopes is stored in MongoDB-CE/Amazon DocumentDB (mcp_scopes_default collection):
+---------------------------------------------------+
| MongoDB-CE/Amazon DocumentDB: mcp_scopes_default |
+---------------------------------------------------+
| Document Structure: |
| |
| { |
| "_id": "registry-admins", | <-- Scope name
| "group_mappings": [ |
| "registry-admins", | <-- Keycloak group name
| "4c46ec66-a4f7-4b62-9095-..." | <-- Entra ID group Object ID
| ], |
| "server_access": [ ... ], | <-- MCP server permissions
| "ui_permissions": { ... } | <-- UI feature access
| } |
+-------------------------------------------+
Mapping Flow¶
+------------------+ +------------------+ +------------------+
| | | | | |
| JWT Token | | Scope | | Access |
| from IdP +---->+ Repository +---->+ Decision |
| | | | | |
+------------------+ +------------------+ +------------------+
| | |
| groups claim: | Query: | Result:
| ["5f605d68-..."] | Find scopes where | scopes=["public-
| | group_mappings | mcp-users"]
| | contains "5f605d68-" |
v v v
Keycloak example: Entra ID example:
groups: ["public-mcp-users"] groups: ["5f605d68-06bc-4208-b992-bb378eee12c5"]
| |
+------------------------------+
|
v
+-------+-------+
| |
| Mapped to: |
| public-mcp- |
| users scope |
| |
+---------------+
Configuration¶
Environment Variables¶
# Provider Selection
AUTH_PROVIDER=entra # or "keycloak"
# Keycloak Configuration
KEYCLOAK_URL=https://keycloak.example.com
KEYCLOAK_REALM=mcp-gateway
KEYCLOAK_CLIENT_ID=mcp-registry
KEYCLOAK_CLIENT_SECRET=...
# Entra ID Configuration
ENTRA_TENANT_ID=6e6ee81b-6bf3-495d-a7fc-d363a551f765
ENTRA_CLIENT_ID=1bd17ba1-aad3-447f-be0b-26f8f9ee859f
ENTRA_CLIENT_SECRET=...
# Token Validation
SECRET_KEY=... # For self-signed tokens
JWT_ISSUER=mcp-auth-server
JWT_AUDIENCE=mcp-registry
Scopes Configuration (scopes.yml or MongoDB)¶
# Group mappings - maps IdP group identifiers to scope names
group_mappings:
# Entra ID uses Object IDs (GUIDs)
"4c46ec66-a4f7-4b62-9095-b7958662f4b6":
- registry-admins
- mcp-servers-unrestricted/read
- mcp-servers-unrestricted/execute
"5f605d68-06bc-4208-b992-bb378eee12c5":
- public-mcp-users
# Keycloak uses group names
"registry-admins":
- registry-admins
"public-mcp-users":
- public-mcp-users
Adding a New Provider¶
To add support for a new identity provider:
- Create Provider Class (
auth_server/providers/new_provider.py): - Implement
AuthProviderbase class - Handle OIDC/OAuth2 flows
-
Implement token validation via JWKS
-
Create IAM Manager (
registry/utils/new_provider_manager.py): - Implement user/group CRUD operations
-
Handle provider-specific API calls
-
Update Factory (
registry/utils/iam_manager.py): -
Add new provider case to
get_iam_manager() -
Update Auth Factory (
auth_server/providers/factory.py): -
Add new provider case to factory function
-
Configure Group Mappings:
- Add group identifiers to
scopes.ymlor MongoDB-CE/Amazon DocumentDB - Document group identifier format (names vs IDs)
Security Considerations¶
- Token Validation: Always validate JWT signatures against provider JWKS
- Admin Credentials: Store IdP admin credentials securely (environment variables, secrets manager)
- Principle of Least Privilege: Request minimal permissions for IAM operations
- Eventual Consistency: Handle Entra ID's eventual consistency with retry logic
- Token Expiry: Respect token expiration times; implement refresh where needed