Authentication and Authorization¶
The MCP Gateway Registry provides enterprise-ready authentication and authorization using industry-standard OAuth 2.0 flows with fine-grained access control.
Overview¶
The authentication system supports three distinct identity scenarios:
- Human Users - Interactive users accessing the Registry UI via browser
- Programmatic Access - Self-signed JWT tokens for CLI tools and AI coding assistants
- Workload Identity (M2M) - Service accounts for AI agents and automated systems
Related Documentation¶
Design Documents¶
For architectural details and design decisions:
- Authentication Design - Detailed auth flows for human users, programmatic access, and M2M workloads
- Multi-Provider IdP Support - Architecture for supporting multiple identity providers (Keycloak, Entra ID)
Configuration Guides¶
For setup and configuration:
- Scopes Management - Scope configuration file format and fine-grained access control
- Authentication Management - Managing users, groups, and scopes via CLI
- Microsoft Entra ID Setup - Entra ID-specific setup and configuration
- Complete Setup Guide - End-to-end deployment instructions
Authentication Architecture¶
Identity Types¶
The system distinguishes between three types of identities, each with different authentication flows:
| Identity Type | Use Case | Auth Method | Token Signing | Lifetime |
|---|---|---|---|---|
| Human Users | Browser UI | OAuth2 Authorization Code | RS256 (IdP) | Session-based |
| Programmatic | CLI, AI assistants | Self-signed JWT | HS256 (SECRET_KEY) | 8 hours |
| M2M Workloads | AI agents, automation | OAuth2 Client Credentials | RS256 (IdP) | 1 hour |
Supported Identity Providers¶
The registry supports multiple identity providers through a pluggable architecture:
- Keycloak - Open-source identity management
- Microsoft Entra ID - Enterprise Azure AD integration
Provider selection is controlled by the AUTH_PROVIDER environment variable:
High-Level Authentication Flow¶
sequenceDiagram
participant User as User/Developer
participant Agent as AI Agent
participant Auth as Keycloak/Entra ID<br/>(Identity Provider)
participant Gateway as NGINX Gateway
participant AuthServer as Auth Server
participant Registry as Registry API
Note over User,Registry: Human User Flow (Browser)
User->>Gateway: 1. Access Registry UI
Gateway->>Auth: 2. Redirect to IdP login
Auth->>User: 3. Login page
User->>Auth: 4. Authenticate
Auth->>Gateway: 5. Authorization code
Gateway->>AuthServer: 6. Exchange code for tokens
AuthServer->>Auth: 7. Validate & get user info
AuthServer->>User: 8. Set session cookie
User->>Registry: 9. Access API with session
Note over User,Registry: Programmatic Access (JWT Token)
User->>AuthServer: 10. Request JWT token (via UI)
AuthServer->>User: 11. Self-signed JWT (HS256)
User->>Agent: 12. Configure agent with token
Agent->>Gateway: 13. API request with Bearer token
Gateway->>AuthServer: 14. Validate token (/validate)
AuthServer->>Gateway: 15. User context + permissions
Gateway->>Registry: 16. Proxied request Authorization Model¶
Scope-Based Access Control¶
Authorization is based on scopes that define:
- Server Access - Which MCP servers and methods users can access
- Agent Actions - Which agent operations users can perform
- UI Permissions - Which UI features are available
Group-to-Scope Mapping¶
User permissions are determined by mapping IdP groups to scopes stored in MongoDB/DocumentDB:
flowchart LR
subgraph IdP["Identity Provider"]
KC["Keycloak Group<br/>registry-admins"]
EA["Entra ID Group<br/>4c46ec66-a4f7-..."]
end
subgraph DB["MongoDB/DocumentDB"]
SM["Scope: registry-admins<br/>group_mappings:<br/>- registry-admins<br/>- 4c46ec66-a4f7-..."]
end
subgraph Perms["Permissions"]
SA["server_access:<br/>server: *<br/>methods: [all]<br/>tools: [all]"]
UI["ui_permissions:<br/>list_agents: [all]<br/>publish_agent: [all]<br/>..."]
end
KC --> SM
EA --> SM
SM --> SA
SM --> UI
%% Dark mode text visibility
classDef idpStyle fill:#e3f2fd,stroke:#1976d2,stroke-width:2px,color:#000
classDef dbStyle fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px,color:#000
classDef permStyle fill:#e8f5e8,stroke:#388e3c,stroke-width:2px,color:#000
class KC,EA idpStyle
class SM dbStyle
class SA,UI permStyle Scope Configuration¶
Scopes are defined in JSON files and loaded into MongoDB. See Scopes Management for the complete file format.
Example: Admin Scope
{
"_id": "registry-admins",
"group_mappings": ["registry-admins", "4c46ec66-a4f7-4b62-9095-b7958662f4b6"],
"server_access": [
{"server": "*", "methods": ["all"], "tools": ["all"]}
],
"ui_permissions": {
"list_agents": ["all"],
"publish_agent": ["all"],
"list_service": ["all"],
"toggle_service": ["all"]
}
}
Example: Limited User Scope
{
"_id": "public-mcp-users",
"group_mappings": ["public-mcp-users", "5f605d68-06bc-4208-b992-bb378eee12c5"],
"server_access": [
{"server": "context7", "methods": ["initialize", "tools/list", "tools/call"], "tools": ["*"]}
],
"ui_permissions": {
"list_service": ["all"],
"list_agents": ["/flight-booking"],
"get_agent": ["/flight-booking"]
}
}
Token Validation Flow¶
All API requests are validated by the auth server through NGINX's auth_request directive:
sequenceDiagram
participant Client as CLI/Agent
participant NGINX as NGINX Gateway
participant Auth as Auth Server
participant IdP as Identity Provider
participant API as Registry API
Client->>NGINX: 1. API Request<br/>Authorization: Bearer <token>
NGINX->>Auth: 2. auth_request /validate
alt Self-Signed Token (iss: mcp-auth-server)
Auth->>Auth: 3a. Validate with SECRET_KEY (HS256)
else IdP Token (iss: Keycloak/Entra)
Auth->>IdP: 3b. Fetch JWKS
IdP-->>Auth: Public keys
Auth->>Auth: 3c. Validate signature (RS256)
end
Auth->>Auth: 4. Extract groups from token
Auth->>Auth: 5. Map groups to scopes
Auth->>Auth: 6. Check server/tool access
alt Access Granted
Auth-->>NGINX: 7a. 200 OK + X-User headers
NGINX->>API: 8. Proxy request
API-->>Client: 9. Response
else Access Denied
Auth-->>NGINX: 7b. 403 Forbidden
NGINX-->>Client: 403 Forbidden
end Key Security Layers¶
Layer 1: Gateway Authentication¶
The NGINX gateway validates all incoming requests:
- Extracts JWT from
Authorizationheader - Calls auth server
/validateendpoint - Sets user context headers for downstream services
Layer 2: Token Validation¶
The auth server supports multiple token types:
| Token Type | Issuer | Algorithm | Validation Method |
|---|---|---|---|
| Self-signed | mcp-auth-server | HS256 | SECRET_KEY |
| Keycloak | {keycloak_url}/realms/{realm} | RS256 | JWKS endpoint |
| Entra ID | https://sts.windows.net/{tenant}/ | RS256 | JWKS endpoint |
Layer 3: Scope-Based Authorization¶
After token validation, the auth server:
- Extracts
groupsclaim from token - Queries MongoDB for matching scopes (via
group_mappings) - Validates requested server/method/tool against
server_accessrules - Returns user context with permissions
Permission Types¶
MCP Server Permissions¶
Control access to MCP servers and their tools:
| Permission | Description |
|---|---|
server | Server name or * for all |
methods | Allowed MCP methods (initialize, tools/list, tools/call, etc.) |
tools | Allowed tool names or * for all |
Agent Permissions¶
Control operations on A2A agents:
| Permission | Description |
|---|---|
list_agents | View agents in listings |
get_agent | View agent details |
publish_agent | Register new agents |
modify_agent | Update existing agents |
delete_agent | Remove agents |
UI Permissions¶
Control access to UI features:
| Permission | Description |
|---|---|
list_service | View MCP servers in dashboard |
register_service | Register new MCP servers |
health_check_service | Run health checks |
toggle_service | Enable/disable servers |
modify_service | Edit server configurations |
Entra ID Group Mapping¶
When using Microsoft Entra ID, group identifiers are Object IDs (GUIDs), not names:
This allows the same scope to work with both Keycloak (group names) and Entra ID (Object IDs).
Finding Entra ID Group Object IDs:
- Azure Portal > Azure Active Directory > Groups
- Select the group
- Copy the "Object ID" from the Overview page
Session Management¶
Human User Sessions¶
Browser sessions use signed cookies:
- Created after successful OAuth2 login
- Contains: username, groups, provider, scopes
- Validated using
SECRET_KEY(HS256) - Default expiry: 8 hours (configurable)
Programmatic Tokens¶
Self-signed JWT tokens for CLI/API access:
- Generated via "Get JWT Token" in UI
- Contains: username, groups, scopes, permissions
- Signed with
SECRET_KEY(HS256) - Default expiry: 8 hours
M2M Tokens¶
Service account tokens from IdP:
- Obtained via OAuth2 Client Credentials flow
- Signed by IdP (RS256)
- Default expiry: 1 hour
- Must be refreshed periodically
Security Best Practices¶
- Use HTTPS - All production deployments should use TLS
- Rotate Secrets - Regularly rotate SECRET_KEY and client secrets
- Least Privilege - Assign minimal required permissions to users/agents
- Audit Logging - Monitor authentication events and access patterns
- Token Expiry - Use short-lived tokens and implement refresh flows
Troubleshooting¶
Common Issues¶
Token validation fails:
- Check token issuer matches expected provider
- Verify JWKS endpoint is accessible
- Ensure SECRET_KEY matches between auth server instances
Permission denied:
- Verify user's groups in IdP
- Check group_mappings in scope configuration
- Ensure scope includes required server/method access
Group not recognized:
- For Entra ID: Use Object ID, not group name
- Verify group exists in group_mappings array
- Reload scopes after configuration changes
Debug Endpoints¶
# Check user context
curl -H "Authorization: Bearer $TOKEN" \
https://registry.example.com/api/debug/user-context
# List available scopes
curl -H "Authorization: Bearer $TOKEN" \
https://registry.example.com/api/scopes
Additional Resources¶
- Authentication Design - Detailed auth flow diagrams
- IdP Provider Support - Provider architecture
- Scopes Management - Scope file format reference
- Auth Management - CLI operations guide