Skip to content
Back to skills

2268 Authentication Design 6de6b8b6

BSecurity

**Version:** 1.0 **Last Updated:** 2026-01-18

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
developmenttypescriptpythongobashtestingapifrontendbackenddocumentation

Works with

  • cursor
  • cli
  • api
  • mcp

Security analysis

B75/100
  • criticalExfiltrates credentials via HTTP — exact pattern from Snyk ToxicSkills study
  • criticalSends environment variables or credentials to an external URL

Pro shows the line behind each finding and how to fix it

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 2268-authentication-design_6de6b8b6 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 2268 Authentication Design 6de6b8b6?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 2268 Authentication Design 6de6b8b6
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-2268-authentication-design-6de6b8b6/badge)](https://www.skillsdirectory.com/skills/tools-only-2268-authentication-design-6de6b8b6)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# Authentication and Authorization Design

**Version:** 1.0
**Last Updated:** 2026-01-18

## Related Documentation

- [Multi-Provider IdP Support](./idp-provider-support.md) - Architecture for supporting multiple identity providers
- [Authentication & Authorization Guide](../auth.md) - Operational guide with setup instructions
- [Microsoft Entra ID Integration](../entra.md) - Entra ID-specific setup and configuration

## Overview

The MCP Gateway Registry implements a comprehensive authentication and authorization system supporting three distinct identity scenarios:

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

## Identity Types

```
+------------------+------------------+------------------+
|   Human Users    | Programmatic     | Workload         |
|                  | Access           | Identity (M2M)   |
+------------------+------------------+------------------+
|                  |                  |                  |
| - Interactive    | - CLI tools      | - AI Agents      |
|   browser login  | - AI coding      | - Automated      |
| - OAuth2 flow    |   assistants     |   pipelines      |
| - Session-based  | - Scripts        | - Service-to-    |
|                  |                  |   service        |
+------------------+------------------+------------------+
|                  |                  |                  |
| Auth Method:     | Auth Method:     | Auth Method:     |
| Authorization    | Self-signed      | OAuth2 Client    |
| Code Flow        | JWT (HS256)      | Credentials Flow |
|                  |                  | (RS256)          |
+------------------+------------------+------------------+
```

---

## Part 1: Human User Authentication

### 1.1 OAuth2 Authorization Code Flow

Human users authenticate via the configured identity provider (Keycloak or Entra ID) using the standard OAuth2 Authorization Code flow.

```
+-------------+     +--------------+     +--------------+     +-------------+
|   Browser   |     |  Registry    |     | Auth Server  |     | Identity    |
|   (User)    |     |  Frontend    |     |              |     | Provider    |
+------+------+     +------+-------+     +------+-------+     +------+------+
       |                   |                    |                    |
       | 1. Click "Login"  |                    |                    |
       +------------------>|                    |                    |
       |                   |                    |                    |
       | 2. Redirect to    |                    |                    |
       |    Auth Server    |                    |                    |
       |<------------------+                    |                    |
       |                   |                    |                    |
       | 3. GET /oauth2/login/entra             |                    |
       +--------------------------------------->|                    |
       |                   |                    |                    |
       |         4. Redirect to IdP authorize endpoint               |
       |<-----------------------------------------------------------+
       |                   |                    |                    |
       |                   5. User authenticates with IdP            |
       +------------------------------------------------------------>|
       |<------------------------------------------------------------+
       |                   |                    |                    |
       | 6. Redirect with authorization code    |                    |
       +--------------------------------------->|                    |
       |                   |                    |                    |
       |                   |  7. Exchange code  |                    |
       |                   |     for tokens     |                    |
       |                   |                    +------------------->|
       |                   |                    |<-------------------+
       |                   |                    |  (ID token +       |
       |                   |                    |   access token)    |
       |                   |                    |                    |
       |    8. Set session cookie + redirect    |                    |
       |<---------------------------------------+                    |
       |                   |                    |                    |
       | 9. Access Registry with session cookie |                    |
       +------------------>|                    |                    |
       |                   |                    |                    |
```

### 1.2 Session Data

After successful authentication, the auth server creates a session containing:

```json
{
  "user_id": "user@example.onmicrosoft.com",
  "email": "user@example.com",
  "groups": ["5f605d68-06bc-4208-b992-bb378eee12c5"],
  "provider": "entra",
  "scopes": ["public-mcp-users"],
  "is_admin": false,
  "ui_permissions": {
    "list_service": ["all"],
    "list_agents": ["/flight-booking"],
    "get_agent": ["/flight-booking"]
  }
}
```

### 1.3 UI Permission Enforcement

The Registry UI enforces feature access based on `ui_permissions` from the user's mapped scopes.

#### Example: `public-mcp-users` Scope

From `cli/examples/public-mcp-users.json`:

```json
{
  "scope_name": "public-mcp-users",
  "ui_permissions": {
    "list_service": ["all"],
    "list_agents": ["/flight-booking"],
    "get_agent": ["/flight-booking"]
  }
}
```

**What this user CAN do:**
- View all MCP servers in the dashboard (`list_service: ["all"]`)
- View the flight-booking agent details (`list_agents`, `get_agent` for `/flight-booking`)
- Access public MCP servers: context7, cloudflare-docs (via `server_access` rules)

**What this user CANNOT do:**
- Publish, modify, or delete agents
- Register or modify MCP servers
- Toggle services on/off
- Access health check for all servers (only context7, cloudflare-docs)
- Access IAM management features

#### Example: `registry-admins` Scope

Admins have unrestricted access to all UI features:

```yaml
# From scopes.yml
UI-Scopes:
  registry-admins:
    list_agents: [all]
    get_agent: [all]
    publish_agent: [all]
    modify_agent: [all]
    delete_agent: [all]
    list_service: [all]
    register_service: [all]
    health_check_service: [all]
    toggle_service: [all]
    modify_service: [all]
```

### 1.4 Frontend Permission Checks

The frontend checks `ui_permissions` before rendering features:

```typescript
// From Dashboard.tsx
const hasUiPermission = useCallback((permission: string, servicePath: string): boolean => {
  const permissions = user?.ui_permissions?.[permission];
  if (!permissions) return false;

  const serviceName = servicePath.replace(/^\//, '');
  return permissions.includes('all') || permissions.includes(serviceName);
}, [user?.ui_permissions]);

// Usage in JSX
<ServerCard
  canHealthCheck={hasUiPermission('health_check_service', server.path)}
  canToggle={hasUiPermission('toggle_service', server.path)}
  // ...
/>
```

---

## Part 2: Programmatic Access (Self-Signed JWT Tokens)

Human users can generate API tokens for programmatic access (CLI tools, AI coding assistants) via the "Get JWT Token" button in the UI.

### 2.1 Token Generation Flow

```
+-------------+     +--------------+     +--------------+     +-------------+
|   Browser   |     |  Registry    |     | Auth Server  |     | MongoDB     |
|   (User)    |     |  Backend     |     |              |     | (Scopes)    |
+------+------+     +------+-------+     +------+-------+     +------+------+
       |                   |                    |                    |
       | 1. Click "Get JWT Token"               |                    |
       +------------------>|                    |                    |
       |                   |                    |                    |
       |                   | 2. POST /api/tokens/generate            |
       |                   |    (with session cookie)                |
       |                   +------------------->|                    |
       |                   |                    |                    |
       |                   |   3. Validate session                   |
       |                   |   Extract: username, groups, provider   |
       |                   |                    |                    |
       |                   |                    | 4. Query group     |
       |                   |                    |    mappings        |
       |                   |                    +------------------->|
       |                   |                    |<-------------------+
       |                   |                    |  (scopes for       |
       |                   |                    |   user's groups)   |
       |                   |                    |                    |
       |                   |   5. Build JWT claims:                  |
       |                   |   - iss: mcp-auth-server                |
       |                   |   - aud: mcp-registry                   |
       |                   |   - sub: username                       |
       |                   |   - groups: [group IDs]                 |
       |                   |   - scope: mapped scopes                |
       |                   |   - exp: 8 hours                        |
       |                   |                    |                    |
       |                   |   6. Sign JWT with SECRET_KEY (HS256)   |
       |                   |                    |                    |
       |                   | 7. Return JWT      |                    |
       |                   |<-------------------+                    |
       |                   |                    |                    |
       | 8. Display token  |                    |                    |
       |<------------------+                    |                    |
```

### 2.2 Self-Signed JWT Structure

```json
{
  "iss": "mcp-auth-server",
  "aud": "mcp-registry",
  "sub": "user@example.onmicrosoft.com",
  "preferred_username": "user@example.onmicrosoft.com",
  "email": "user@example.com",
  "groups": ["5f605d68-06bc-4208-b992-bb378eee12c5"],
  "scope": "public-mcp-users",
  "token_use": "access",
  "auth_method": "oauth2",
  "provider": "entra",
  "iat": 1768685565,
  "exp": 1768714365,
  "description": "Generated via sidebar"
}
```

### 2.3 Using the Token with CLI Tools

```bash
# Save token to file
echo "eyJhbGciOiJIUzI1NiIs..." > .token

# Use with registry_management.py
uv run python api/registry_management.py \
  --token-file .token \
  --registry-url http://localhost \
  server-search --query "documentation"

# Use with curl
curl -H "Authorization: Bearer $(cat .token)" \
  http://localhost/api/servers
```

### 2.4 Token Validation Flow (API Usage)

```
+-------------+     +--------------+     +--------------+     +-------------+
|   CLI /     |     |    NGINX     |     | Auth Server  |     | MCP Server  |
|   Client    |     |   Gateway    |     |              |     |             |
+------+------+     +------+-------+     +------+-------+     +------+------+
       |                   |                    |                    |
       | 1. API Request    |                    |                    |
       |    Authorization: Bearer <JWT>         |                    |
       +------------------>|                    |                    |
       |                   |                    |                    |
       |                   | 2. auth_request /validate               |
       |                   +------------------->|                    |
       |                   |                    |                    |
       |                   |   3. Check token issuer                 |
       |                   |   iss == "mcp-auth-server"?             |
       |                   |                    |                    |
       |                   |   4. If yes: validate with              |
       |                   |      SECRET_KEY (HS256)                 |
       |                   |                    |                    |
       |                   |   5. If no: try IdP JWKS                |
       |                   |      validation (RS256)                 |
       |                   |                    |                    |
       |                   |   6. Extract scopes, validate           |
       |                   |      server/tool access                 |
       |                   |                    |                    |
       |                   | 7. 200 OK + X-User headers              |
       |                   |<-------------------+                    |
       |                   |                    |                    |
       |                   | 8. Proxy request   |                    |
       |                   +--------------------------------------->|
       |                   |                    |                    |
       | 9. Response       |                    |                    |
       |<------------------+                    |                    |
```

---

## Part 3: Workload Identity (M2M / Service Accounts)

AI agents and automated systems use service accounts with client credentials for authentication.

### 3.1 M2M Identity in Identity Providers

```
+---------------------------+---------------------------+
|        Keycloak           |      Microsoft Entra ID   |
+---------------------------+---------------------------+
|                           |                           |
| Service Account Client:   | App Registration:         |
| - Client ID               | - Application (client) ID |
| - Client Secret           | - Client Secret           |
| - Service Account User    | - Service Principal       |
| - Group Memberships       | - Group Memberships       |
|                           |                           |
+---------------------------+---------------------------+
```

### 3.2 M2M Account Creation Flow (Entra ID)

```
+-------------+     +--------------+     +--------------+     +-------------+
|   Admin     |     |  Registry    |     | Entra ID     |     | MongoDB     |
|   CLI       |     |  Backend     |     | Graph API    |     |             |
+------+------+     +------+-------+     +------+-------+     +------+------+
       |                   |                    |                    |
       | 1. user-create-m2m --name pub-m2m-bot --groups public-mcp-users
       +------------------>|                    |                    |
       |                   |                    |                    |
       |                   | 2. Create App Registration              |
       |                   +------------------->|                    |
       |                   |<-------------------+                    |
       |                   |   (app_id, object_id)                   |
       |                   |                    |                    |
       |                   | 3. Create Service Principal             |
       |                   +------------------->|                    |
       |                   |<-------------------+                    |
       |                   |   (service_principal_id)                |
       |                   |                    |                    |
       |                   | 4. Create Client Secret                 |
       |                   +------------------->|                    |
       |                   |<-------------------+                    |
       |                   |   (client_secret)                       |
       |                   |                    |                    |
       |                   | 5. Add SP to group (with retry)         |
       |                   +------------------->|                    |
       |                   |<-------------------+                    |
       |                   |                    |                    |
       | 6. Return credentials                  |                    |
       |   client_id, client_secret             |                    |
       |<------------------+                    |                    |
```

### 3.3 M2M Token Request Flow

AI agents use OAuth2 Client Credentials flow to obtain access tokens:

```
+-------------+     +--------------+     +--------------+
| AI Agent    |     | Identity     |     | Registry     |
| (M2M)       |     | Provider     |     | API          |
+------+------+     +------+-------+     +------+-------+
       |                   |                    |
       | 1. POST /oauth2/v2.0/token             |
       |    grant_type=client_credentials       |
       |    client_id=...                       |
       |    client_secret=...                   |
       |    scope=api://.../.default            |
       +------------------>|                    |
       |                   |                    |
       | 2. Access Token (RS256, 1 hour)        |
       |<------------------+                    |
       |                   |                    |
       | 3. API Request with token              |
       +--------------------------------------->|
       |                   |                    |
       |                   |   4. Validate via  |
       |                   |      IdP JWKS      |
       |                   |                    |
       | 5. Response       |                    |
       |<--------------------------------------+
```

### 3.4 Generating M2M Tokens

Use the credentials provider script to generate tokens:

**Identities File** (`.oauth-tokens/entra-identities.json`):

```json
[
  {
    "identity_name": "pub-m2m-bot",
    "tenant_id": "6e6ee81b-6bf3-495d-a7fc-d363a551f765",
    "client_id": "c50b03cf-6f7b-4fae-846e-7910a4100020",
    "client_secret": "your-client-secret",
    "scope": "api://1bd17ba1-aad3-447f-be0b-26f8f9ee859f/.default"
  }
]
```

**Generate Token:**

```bash
cd credentials-provider
uv run python entra/generate_tokens.py \
  --identities-file ../.oauth-tokens/entra-identities.json \
  --output-dir ../.oauth-tokens
```

**Output** (`.oauth-tokens/pub-m2m-bot.json`):

```json
{
  "identity_name": "pub-m2m-bot",
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 3599,
  "generated_at": "2026-01-18T02:30:56.123456+00:00",
  "expires_at": "2026-01-18T03:30:55.123456+00:00",
  "provider": "entra",
  "tenant_id": "6e6ee81b-6bf3-495d-a7fc-d363a551f765",
  "client_id": "c50b03cf-6f7b-4fae-846e-7910a4100020",
  "scope": "api://1bd17ba1-aad3-447f-be0b-26f8f9ee859f/.default"
}
```

### 3.5 M2M Token Structure (from Entra ID)

```json
{
  "aud": "api://1bd17ba1-aad3-447f-be0b-26f8f9ee859f",
  "iss": "https://sts.windows.net/6e6ee81b-6bf3-495d-a7fc-d363a551f765/",
  "iat": 1768703056,
  "nbf": 1768703056,
  "exp": 1768706956,
  "appid": "c50b03cf-6f7b-4fae-846e-7910a4100020",
  "appidacr": "1",
  "groups": ["5f605d68-06bc-4208-b992-bb378eee12c5"],
  "idp": "https://sts.windows.net/6e6ee81b-6bf3-495d-a7fc-d363a551f765/",
  "oid": "5d3d562c-4449-413a-9791-86920d4bf75f",
  "sub": "5d3d562c-4449-413a-9791-86920d4bf75f",
  "tid": "6e6ee81b-6bf3-495d-a7fc-d363a551f765",
  "ver": "1.0"
}
```

**Key Differences from Self-Signed Tokens:**

| Aspect | Self-Signed (Human) | IdP Token (M2M) |
|--------|---------------------|-----------------|
| Issuer | `mcp-auth-server` | `https://sts.windows.net/{tenant}/` |
| Algorithm | HS256 (symmetric) | RS256 (asymmetric) |
| Validation | SECRET_KEY | IdP JWKS endpoint |
| Expiry | 8 hours | 1 hour |
| Subject | username/email | Service principal object ID |

---

## Part 4: Authorization - Scope-Based Access Control

### 4.1 Scope Storage in MongoDB-CE/Amazon DocumentDB

Scopes are stored in the `mcp_scopes_default` collection:

```
+-----------------------------------------------------------------------+
|                    mcp_scopes_default collection                       |
+-----------------------------------------------------------------------+
| {                                                                     |
|   "_id": "public-mcp-users",                                          |
|   "group_mappings": [                                                 |
|     "public-mcp-users",                        <-- Keycloak group     |
|     "5f605d68-06bc-4208-b992-bb378eee12c5"     <-- Entra ID Object ID |
|   ],                                                                  |
|   "server_access": [                                                  |
|     {                                                                 |
|       "server": "context7",                                           |
|       "methods": ["initialize", "tools/list", "tools/call"],          |
|       "tools": ["*"]                                                  |
|     },                                                                |
|     {                                                                 |
|       "server": "api",                                                |
|       "methods": ["initialize", "GET", "POST", "servers", ...],       |
|       "tools": []                                                     |
|     }                                                                 |
|   ],                                                                  |
|   "ui_permissions": {                                                 |
|     "list_service": ["all"],                                          |
|     "list_agents": ["/flight-booking"],                               |
|     "get_agent": ["/flight-booking"]                                  |
|   }                                                                   |
| }                                                                     |
+-----------------------------------------------------------------------+
```

### 4.2 Group-to-Scope Mapping Query

The auth server queries MongoDB-CE/Amazon DocumentDB to find scopes for a given group:

```python
# From scope_repository.py
async def get_group_mappings(self, keycloak_group: str) -> List[str]:
    """Find all scopes where group_mappings array contains this group."""
    collection = await self._get_collection()
    cursor = collection.find({"group_mappings": keycloak_group})
    scope_names = [doc["_id"] async for doc in cursor]
    return scope_names
```

### 4.3 Server/Tool Access Validation

```
+------------------+     +------------------+     +------------------+
|                  |     |                  |     |                  |
|  Request:        |     |  User Scopes:    |     |  Access          |
|  POST /context7  |     |  [public-mcp-    |     |  Decision:       |
|  tools/call      |     |   users]         |     |  GRANTED         |
|                  |     |                  |     |                  |
+--------+---------+     +--------+---------+     +--------+---------+
         |                        |                        |
         |   1. Extract server    |                        |
         |      and method        |                        |
         +----------------------->|                        |
         |                        |                        |
         |   2. For each scope,   |                        |
         |      check server_     |                        |
         |      access rules      |                        |
         |                        +----------------------->|
         |                        |                        |
         |   3. public-mcp-users  |                        |
         |      allows context7   |                        |
         |      with tools/call   |                        |
         |                        |                        |
```

**Validation Logic** (from `server.py`):

```python
def validate_server_tool_access(
    server_name: str,
    method: str,
    tool_name: Optional[str],
    user_scopes: List[str]
) -> bool:
    """Check if user has access to server/method/tool."""
    for scope_name in user_scopes:
        scope_config = get_scope_config(scope_name)
        for server_rule in scope_config.get("server_access", []):
            # Check server name match (exact or wildcard)
            if server_rule["server"] in (server_name, "*"):
                # Check method is allowed
                if method in server_rule["methods"] or "all" in server_rule["methods"]:
                    # Check tool access if specified
                    if tool_name is None or server_rule["tools"] == "*":
                        return True
                    if tool_name in server_rule["tools"]:
                        return True
    return False
```

---

## Summary Comparison

| Aspect | Human User | Programmatic (API Token) | M2M (Workload) |
|--------|------------|--------------------------|----------------|
| **Use Case** | Browser UI | CLI, AI assistants | AI agents, automation |
| **Auth Flow** | OAuth2 Authorization Code | N/A (derived from session) | OAuth2 Client Credentials |
| **Token Issuer** | IdP (Keycloak/Entra) | `mcp-auth-server` | IdP (Keycloak/Entra) |
| **Token Signing** | RS256 (IdP) | HS256 (SECRET_KEY) | RS256 (IdP) |
| **Token Lifetime** | Session-based | 8 hours | 1 hour |
| **Validation** | Session cookie | SECRET_KEY | IdP JWKS |
| **Groups Source** | IdP groups claim | Copied from session | IdP groups claim |
| **Scope Mapping** | Groups -> Datastore scopes | Embedded in token | Groups -> Datastore scopes |
| **Credential Storage** | Browser session | Token file | Client ID/Secret |

---

## Related Documentation

- [Multi-Provider IdP Support](./idp-provider-support.md)
- [Microsoft Entra ID Integration](../entra.md)
- [Management API Testing Guide](../../api/test-management-api-e2e.md)

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.