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 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