Skip to content

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:

  1. Human Users - Interactive users accessing the Registry UI via browser
  2. Programmatic Access - Self-signed JWT tokens for CLI tools and AI coding assistants
  3. Workload Identity (M2M) - Service accounts for AI agents and automated systems

Design Documents

For architectural details and design decisions:

Configuration Guides

For setup and configuration:


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:

AUTH_PROVIDER=keycloak   # Use Keycloak (default)
AUTH_PROVIDER=entra      # Use Microsoft Entra ID

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:

  1. Server Access - Which MCP servers and methods users can access
  2. Agent Actions - Which agent operations users can perform
  3. 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 Authorization header
  • Calls auth server /validate endpoint
  • 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:

  1. Extracts groups claim from token
  2. Queries MongoDB for matching scopes (via group_mappings)
  3. Validates requested server/method/tool against server_access rules
  4. 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:

{
  "group_mappings": [
    "public-mcp-users",
    "5f605d68-06bc-4208-b992-bb378eee12c5"
  ]
}

This allows the same scope to work with both Keycloak (group names) and Entra ID (Object IDs).

Finding Entra ID Group Object IDs:

  1. Azure Portal > Azure Active Directory > Groups
  2. Select the group
  3. 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

  1. Use HTTPS - All production deployments should use TLS
  2. Rotate Secrets - Regularly rotate SECRET_KEY and client secrets
  3. Least Privilege - Assign minimal required permissions to users/agents
  4. Audit Logging - Monitor authentication events and access patterns
  5. 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