|
| 1 | +# ADR-023: One-Time Authentication for Gateway Registration |
| 2 | + |
| 3 | +**Status:** Accepted |
| 4 | +**Date:** 2025-11-10 |
| 5 | +**Deciders:** Keval Mahajan |
| 6 | +**Technical Story:** [#1387](https://github.com/IBM/mcp-context-forge/issues/1387) |
| 7 | + |
| 8 | +## Context and Problem Statement |
| 9 | + |
| 10 | +Context Forge Gateway allows users to register MCP servers with authentication credentials to proxy and expose their tools through virtual servers. Prior to this implementation, the gateway required storing authentication credentials (bearer tokens, basic auth) in the database to maintain persistent connections and perform health checks on registered MCP servers. |
| 11 | + |
| 12 | +However, a significant use case emerged: organizations and users who want to leverage the gateway's tool proxying capabilities but cannot or will not store authentication credentials in the gateway database due to security policies, compliance requirements, or organizational constraints. These users still needed a mechanism to register MCP servers with authentication, discover available tools, and access them through the gateway using runtime-provided credentials via passthrough headers. |
| 13 | + |
| 14 | +The existing authentication flow required credentials to be persisted, making it incompatible with scenarios where: |
| 15 | +- Security policies prohibit credential storage in third-party systems |
| 16 | +- Organizations prefer to use runtime authentication with short-lived tokens |
| 17 | +- Users want to leverage passthrough header mechanisms for authentication |
| 18 | +- Vault plugins or external secret management solutions are not available or suitable |
| 19 | + |
| 20 | +**How can users register authenticated MCP servers and use their tools through the gateway without persisting credentials in the database?** |
| 21 | + |
| 22 | +## Decision Drivers |
| 23 | + |
| 24 | +- Security requirement: Avoid storing authentication credentials in the gateway database |
| 25 | +- Compliance requirement: Meet organizational policies that prohibit credential persistence |
| 26 | +- Usability requirement: Maintain automatic tool discovery and registration benefits |
| 27 | +- Flexibility requirement: Support runtime authentication with passthrough headers |
| 28 | +- Compatibility requirement: Work with existing transport protocols (SSE, STREAMABLEHTTP) |
| 29 | + |
| 30 | +## Considered Options |
| 31 | + |
| 32 | +1. **One-Time Authentication with Passthrough Headers** (Chosen) |
| 33 | +2. Two-Step Registration API (Add gateway, then connect separately) |
| 34 | +3. Mandatory Vault Plugin Integration |
| 35 | +4. Credential-Free Registration with Manual Tool Configuration |
| 36 | + |
| 37 | +## Decision Outcome |
| 38 | + |
| 39 | +Chosen option: **"One-Time Authentication with Passthrough Headers"**, because it provides the optimal balance between security, usability, and flexibility. It enables automatic tool discovery while ensuring credentials are never persisted, and it works seamlessly with the existing passthrough header infrastructure. |
| 40 | + |
| 41 | +### Implementation Details |
| 42 | + |
| 43 | +The solution introduces a `one_time_auth` boolean flag in the gateway registration API (`POST /gateways`). When enabled, the authentication flow works as follows: |
| 44 | + |
| 45 | +1. **Initial Registration**: User provides authentication credentials (`auth_type` and `auth_token`) along with `one_time_auth: true` in the registration request |
| 46 | +2. **One-Time Connection**: Gateway uses the provided credentials exactly once to establish a connection with the MCP server |
| 47 | +3. **Tool Discovery**: During this single authenticated connection, the gateway performs complete tool discovery, retrieving all available tools, their schemas, and metadata |
| 48 | +4. **Credential Discard**: After tool discovery completes successfully, the authentication credentials are immediately discarded and not persisted to the database |
| 49 | +5. **Passthrough Configuration**: Users must configure `passthrough_headers` (specifically `X-Upstream-Authorization` for authorization headers) to enable runtime authentication |
| 50 | +6. **Runtime Authentication**: Subsequent requests to the MCP server tools must include authentication credentials via passthrough headers provided by the client |
| 51 | + |
| 52 | +```mermaid |
| 53 | +graph LR |
| 54 | + A[User] --> B["Add MCP Server"] |
| 55 | + B --> C{"Enable One-Time Authentication?"} |
| 56 | + C -->|Yes| D["Do Not Store Credentials in DB"] |
| 57 | + C -->|No| E["Store Credentials in DB"] |
| 58 | + D --> F["Configure Passthrough Headers<br/>(X-Upstream-Authorization)"] |
| 59 | + F --> G["Create Virtual Server"] |
| 60 | + G --> H["Link to MCP Server"] |
| 61 | + H --> I["Add Authentication Headers"] |
| 62 | + I --> J["Test Connection"] |
| 63 | + J --> K["Successful Authentication"] |
| 64 | + E --> L["Create Virtual Server with Stored Credentials"] |
| 65 | +
|
| 66 | + classDef step fill:#1e1e1e,stroke:#ffffff,stroke-width:2px,color:#f5f5f5; |
| 67 | + class A,B,C,D,E,F,G,H,I,J,K,L step; |
| 68 | +``` |
| 69 | + |
| 70 | +### Technical Changes |
| 71 | + |
| 72 | +Key technical changes include: |
| 73 | + |
| 74 | +- Added `one_time_auth` boolean field to the gateway registration schema |
| 75 | +- Modified the gateway registration flow to conditionally store or discard credentials based on the flag |
| 76 | +- Implemented automatic disabling of health checks for one-time auth gateways (since no stored credentials are available for health check execution) |
| 77 | +- Updated the frontend UI to include a one-time authentication checkbox in the gateway configuration forms |
| 78 | +- Modified the authentication handling logic to support both stored credentials and passthrough header workflows |
| 79 | +- Ensured compatibility with both SSE and STREAMABLEHTTP transport protocols |
| 80 | + |
| 81 | +Authentication Flow: |
| 82 | + |
| 83 | +```mermaid |
| 84 | +sequenceDiagram |
| 85 | + participant User |
| 86 | + participant Gateway |
| 87 | + participant Database |
| 88 | + participant MCP Server |
| 89 | +
|
| 90 | + Note over User,MCP Server: Traditional Flow (Credentials Stored) |
| 91 | + User->>Gateway: POST /gateways (with credentials) |
| 92 | + Gateway->>MCP Server: Connect with credentials |
| 93 | + MCP Server-->>Gateway: Tool list |
| 94 | + Gateway->>Database: Store credentials |
| 95 | + Gateway-->>User: Gateway registered |
| 96 | +
|
| 97 | + Note over User,MCP Server: Later requests |
| 98 | + User->>Gateway: Request tool |
| 99 | + Gateway->>Database: Retrieve credentials |
| 100 | + Gateway->>MCP Server: Call tool (with stored credentials) |
| 101 | + MCP Server-->>Gateway: Tool response |
| 102 | + Gateway-->>User: Response |
| 103 | +
|
| 104 | + Note over User,MCP Server: One-Time Auth Flow (Credentials NOT Stored) |
| 105 | + User->>Gateway: POST /gateways (one_time_auth=true, credentials) |
| 106 | + Gateway->>MCP Server: Connect with credentials (ONE TIME) |
| 107 | + MCP Server-->>Gateway: Tool list |
| 108 | + Gateway->>Gateway: Discard credentials |
| 109 | + Gateway-->>User: Gateway registered (no credentials saved) |
| 110 | +
|
| 111 | + Note over User,MCP Server: Later requests |
| 112 | + User->>Gateway: Request tool (with X-Upstream-Authorization header) |
| 113 | + Gateway->>MCP Server: Call tool (forward passthrough auth) |
| 114 | + MCP Server-->>Gateway: Tool response |
| 115 | + Gateway-->>User: Response |
| 116 | +``` |
| 117 | + |
| 118 | + |
| 119 | +### Positive Consequences |
| 120 | + |
| 121 | +- **Enhanced Security Posture**: Credentials are never persisted in the gateway database, reducing the attack surface and exposure risk |
| 122 | +- **Compliance Enablement**: Organizations with strict security policies can now use the gateway without violating credential storage restrictions |
| 123 | +- **Runtime Authentication Flexibility**: Users can rotate credentials, use short-lived tokens, or implement dynamic authentication strategies without updating gateway configuration |
| 124 | +- **Preserved Tool Discovery**: Users still benefit from automatic tool discovery and schema registration without manual configuration |
| 125 | +- **Backward Compatibility**: The feature is opt-in and does not affect existing gateway registration workflows |
| 126 | + |
| 127 | +### Negative Consequences |
| 128 | + |
| 129 | +- **Health Check Limitation**: Health checks are automatically disabled for one-time auth gateways since no stored credentials are available to authenticate health check requests |
| 130 | +- **Client Configuration Complexity**: MCP clients must be configured to provide passthrough headers with authentication credentials for every request, increasing configuration complexity |
| 131 | +- **Credential Management Burden**: Users are responsible for managing and distributing authentication credentials to all clients, rather than centralizing them in the gateway |
| 132 | +- **Reconnection Requirements**: If tools need to be re-discovered or the gateway needs to reconnect, users must re-register the gateway with credentials since none are stored |
| 133 | + |
| 134 | +## Pros and Cons of the Options |
| 135 | + |
| 136 | +### Option 1: One-Time Authentication with Passthrough Headers (Chosen) |
| 137 | + |
| 138 | +**Description**: Introduce a `one_time_auth` flag that uses credentials once for tool discovery, then discards them. Runtime authentication is handled via passthrough headers. |
| 139 | + |
| 140 | +- **Good**, because it eliminates credential persistence security risks |
| 141 | +- **Good**, because it preserves automatic tool discovery benefits |
| 142 | +- **Good**, because it provides flexibility for runtime authentication strategies |
| 143 | +- **Good**, because it is backward compatible and opt-in |
| 144 | +- **Bad**, because health checks cannot be performed without stored credentials |
| 145 | +- **Bad**, because it increases client configuration complexity |
| 146 | + |
| 147 | +### Option 2: Two-Step Registration API |
| 148 | + |
| 149 | +**Description**: Split the `POST /gateways` API into two separate operations: (1) Add gateway metadata, (2) Establish connection and perform tool discovery. |
| 150 | + |
| 151 | +- **Good**, because it separates concerns between registration and authentication |
| 152 | +- **Bad**, because it requires two API calls instead of one atomic operation |
| 153 | +- **Bad**, because it increases implementation complexity |
| 154 | +- **Bad**, because it creates potential for incomplete registrations |
| 155 | +- **Neutral**, because it could enable other use cases in the future |
| 156 | + |
| 157 | +### Option 3: Mandatory Vault Plugin Integration |
| 158 | + |
| 159 | +**Description**: Require all users concerned about credential storage to use the Vault plugin for external secret management. |
| 160 | + |
| 161 | +- **Good**, because it provides centralized secret management |
| 162 | +- **Good**, because it enables health checks with externally stored credentials |
| 163 | +- **Bad**, because not all users have vault infrastructure available |
| 164 | +- **Bad**, because it imposes infrastructure requirements on users |
| 165 | +- **Bad**, because it doesn't support scenarios where runtime passthrough authentication is preferred |
| 166 | + |
| 167 | +### Option 4: Credential-Free Registration with Manual Tool Configuration |
| 168 | + |
| 169 | +**Description**: Allow users to register gateways without any initial authentication and manually configure tool schemas. |
| 170 | + |
| 171 | +- **Good**, because no credentials are ever provided to the gateway |
| 172 | +- **Bad**, because it eliminates automatic tool discovery benefits |
| 173 | +- **Bad**, because it requires extensive manual configuration of tool schemas |
| 174 | +- **Bad**, because it creates maintenance burden when tools change |
| 175 | + |
| 176 | +## Validation |
| 177 | + |
| 178 | +The feature was tested and validated in the following scenarios: |
| 179 | + |
| 180 | +- MCP servers with SSE transport using Bearer authentication |
| 181 | +- MCP servers with SSE transport using Basic authentication |
| 182 | +- MCP servers with STREAMABLEHTTP transport using Bearer authentication |
| 183 | +- MCP servers with STREAMABLEHTTP transport using Basic authentication |
| 184 | +- Tool invocation from Admin UI |
| 185 | +- Tool invocation from MCP Inspector via virtual server |
| 186 | + |
| 187 | +All test scenarios successfully validated that: |
| 188 | +- Credentials were not stored in the database |
| 189 | +- Tool discovery completed successfully during one-time authentication |
| 190 | +- Tool calls functioned correctly when authentication was provided via passthrough headers |
| 191 | +- Both transport protocols worked as expected |
| 192 | + |
| 193 | +## Links |
| 194 | + |
| 195 | +- GitHub Pull Request: [#1407](https://github.com/IBM/mcp-context-forge/pull/1407) |
| 196 | +- GitHub Issue: [#1387](https://github.com/IBM/mcp-context-forge/issues/1387) |
| 197 | +- Usage Documentation: `https://ibm.github.io/mcp-context-forge/overview/passthrough/#usage-with-one-time-auth` |
| 198 | +- MCP Authorization Specification: OAuth 2.1 with Protected Resource Metadata (RFC 9728) |
| 199 | + |
| 200 | +## Notes |
| 201 | + |
| 202 | +- Documentation for this feature has been added to `docs/docs` including usage examples with Claude Desktop configuration |
| 203 | +- The feature supports both bearer and basic authentication schemes |
| 204 | +- The `X-Upstream-Authorization` passthrough header is mapped to the `Authorization` header when forwarding requests to upstream MCP servers |
| 205 | +- Implementation maintains compatibility with existing gateway features including virtual servers, tool proxying, and RBAC |
| 206 | +- Lint checks (`make lint`) and test suite (`make test`) pass successfully |
| 207 | +- CHANGELOG has been updated with user-facing changes |
0 commit comments