Skip to content

docs: add per-user OAuth documentation and API endpoints#2598

Merged
akshaydeo merged 1 commit intomainfrom
04-09-docs_adds_docs_for_per_user_mcp_oauth
Apr 9, 2026
Merged

docs: add per-user OAuth documentation and API endpoints#2598
akshaydeo merged 1 commit intomainfrom
04-09-docs_adds_docs_for_per_user_mcp_oauth

Conversation

@Pratham-Mishra04
Copy link
Copy Markdown
Collaborator

Summary

Adds comprehensive per-user OAuth 2.1 support for MCP clients, enabling each end-user to authenticate with upstream services (Notion, GitHub, etc.) using their own credentials instead of shared admin tokens. Also introduces a unified model alias system to map model names to provider-specific identifiers.

Changes

  • Per-User OAuth Implementation: Complete OAuth 2.1 authorization server with dynamic client registration (RFC 7591), PKCE support (RFC 7636), and OAuth discovery (RFC 8414, RFC 9728)
  • Consent Flow: Multi-step browser-based consent system allowing users to select identity (Virtual Key, User ID, or session-only) and connect upstream services
  • Cross-Gateway Token Sharing: Tokens stored against persistent identities work across both MCP Gateway and LLM Gateway
  • Lazy Authentication: Runtime auth for services skipped during consent, with auth URLs returned in tool results
  • Model Alias System: Unified top-level aliases field replacing provider-specific deployments configurations
  • Breaking Changes: Provider deployments removed, Go SDK field renames for model tracking
  • Documentation: Comprehensive guides for per-user OAuth setup, flows, and migration

Type of change

  • Feature
  • Bug fix
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (Next.js)
  • Docs

How to test

Per-User OAuth Flow

# 1. Configure an MCP client with per_user_oauth via Web UI
# 2. Test MCP client connection (Claude Code, Cursor)
curl -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -d '{"method": "tools/list"}'
# Should return 401 with WWW-Authenticate header

# 3. Test OAuth discovery
curl http://localhost:8080/.well-known/oauth-protected-resource
curl http://localhost:8080/.well-known/oauth-authorization-server

# 4. Test dynamic client registration
curl -X POST http://localhost:8080/api/oauth/per-user/register \
  -H "Content-Type: application/json" \
  -d '{"client_name":"Test","redirect_uris":["http://localhost:3000/callback"]}'

Model Aliases

# Test alias resolution in chat completions
curl -X POST http://localhost:8080/v1/chat/completions \
  -H "Authorization: Bearer vk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"model":"my-custom-alias","messages":[{"role":"user","content":"test"}]}'

Core/Transports

go version
go test ./...

UI

cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build

Screenshots/Recordings

  • Identity selection screen for consent flow
  • MCP services connection interface
  • Per-user OAuth setup in Web UI
  • Auth URL presentation in Claude Code and LLM responses

Breaking changes

  • Yes
  • No

Breaking Changes in v1.5.0-prerelease2:

  1. Provider deployments removed - Azure, Bedrock, Vertex, and Replicate deployment maps must migrate to the unified top-level aliases field
  2. Go SDK: ExtraFields.ModelRequested replaced by OriginalModelRequested + ResolvedModelUsed
  3. Go SDK: StreamAccumulatorResult.Model replaced by RequestedModel + ResolvedModel

See the v1.5.0 Migration Guide for full before/after examples and automatic migration details.

Related issues

Implements per-user OAuth authentication for MCP clients and introduces unified model aliasing system.

Security considerations

  • PKCE Required: All OAuth flows require PKCE with S256 method for security
  • Browser Binding: HttpOnly SameSite=Lax cookies prevent CSRF attacks during consent flows
  • Token Isolation: Per-user tokens are scoped to individual identities with no cross-user access
  • Session Management: 24-hour session tokens with automatic cleanup of expired flows/codes
  • Identity Validation: Virtual Keys validated against database; User IDs are self-declared following existing trust model

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

Copy link
Copy Markdown
Collaborator Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 9, 2026

📝 Walkthrough

Summary by CodeRabbit

  • Documentation
    • Added comprehensive Per-User OAuth support documentation for MCP Gateway
    • Expanded authentication options to include per-user OAuth for HTTP and SSE connections
    • Documented new OAuth 2.1 authorization server capabilities and consent workflows
    • Updated API reference with endpoints for dynamic client registration and token exchange

Walkthrough

This PR adds comprehensive documentation and OpenAPI specifications for per-user OAuth 2.1 support. Changes include new MCP documentation pages explaining per-user authentication workflows, updated authentication descriptions in existing guides, and extensive API endpoint definitions for OAuth authorization, consent flows, and discovery mechanisms.

Changes

Cohort / File(s) Summary
Changelog Updates
docs/changelogs/v1.5.0-prerelease2.mdx
Added model alias feature documentation and explicit breaking-change entries for v1.5.0 (provider deployments removal, Go SDK renames) plus corresponding feature notes under Core and Framework versions.
Navigation and Index
docs/docs.json
Registered new mcp/per-user-oauth documentation page in the "MCP Gateway" navigation group.
MCP Documentation
docs/mcp/overview.mdx, docs/mcp/per-user-oauth.mdx, docs/mcp/connecting-to-servers.mdx, docs/mcp/gateway-url.mdx, docs/mcp/oauth.mdx
Added new per-user OAuth capability card; created comprehensive per-user-oauth guide covering Web UI setup, consent workflows, identity selection, token issuance, and cross-gateway behavior; clarified existing OAuth as admin-managed shared token; updated connection-type tables and SSE authentication sections to reflect per-user OAuth option; added gateway URL behavior documentation for OAuth discovery and lazy authentication.
OpenAPI Specifications (JSON/YAML)
docs/openapi/openapi.json, docs/openapi/openapi.yaml
Updated root API specs with new per-user OAuth endpoints, dynamic client registration route, and discovery metadata endpoints; added per_user_oauth to auth_type enum with distinguishing description; expanded response components.
OpenAPI OAuth Paths
docs/openapi/paths/management/oauth.yaml
Defined complete per-user OAuth 2.1 authorization server with dynamic client registration, authorization endpoint (PKCE flow), token exchange, upstream proxy authorize, consent-flow UI routes (identity/MCP selection, submission handlers), and OAuth discovery well-known endpoints.
OpenAPI OAuth Schemas
docs/openapi/schemas/management/oauth.yaml
Extended MCPAuthType enum to include per_user_oauth; added new schema definitions for client registration request/response, token response, and OAuth metadata discovery structures.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 Per-user OAuth blooms so bright,
Consent flows dance through web and night!
Each user's token, unique and true,
Bifrost's magic makes it new,
Carrots shared, but credentials stay,
Authentication hops the way! 🥕✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: adding per-user OAuth documentation and API endpoints, which aligns with the primary focus of the changeset.
Description check ✅ Passed The PR description is comprehensive and follows the template structure, including summary, detailed changes, type of change, affected areas, testing instructions, breaking changes, and security considerations.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 04-09-docs_adds_docs_for_per_user_mcp_oauth

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 9, 2026

🧪 Test Suite Available

This PR can be tested by a repository admin.

Run tests for PR #2598

@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 04-09-docs_adds_docs_for_per_user_mcp_oauth branch from bb017b5 to d6f9c40 Compare April 9, 2026 16:08
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 9, 2026

Confidence Score: 5/5

Safe to merge — all findings are P2 style/consistency issues in schema descriptions with no functional impact.

The PR is documentation-only. All three comments are P2 style fixes (version string typo, stale field description, header casing). None affects correctness, data, or user-visible behavior.

docs/openapi/schemas/management/mcp.yaml — oauth_config_id descriptions (3 occurrences) and MCPAuthType version string should be updated to mention per_user_oauth and OAuth 2.1 respectively.

Vulnerabilities

No security concerns identified. The documentation accurately describes the implemented security controls: PKCE (S256 only) required on all OAuth flows, HttpOnly SameSite=Lax cookies for browser-binding/CSRF protection, token isolation per user identity, and 24-hour session TTLs with automatic cleanup.

Important Files Changed

Filename Overview
docs/mcp/per-user-oauth.mdx New page documenting per-user OAuth 2.1 flow — well-structured and thorough, but the bash examples have inconsistent header casing (x-bf-virtual-key vs X-Bf-User-Id)
docs/openapi/schemas/management/mcp.yaml MCPAuthType description uses "OAuth 2.0" for per_user_oauth (should be 2.1); oauth_config_id description in 3 places says "Only relevant when auth_type is 'oauth'" but per_user_oauth also requires this field
docs/openapi/schemas/management/oauth.yaml Adds well-defined schemas for per-user OAuth 2.1: client registration, token response, protected resource metadata, and authorization server metadata — all consistent with RFC references
docs/openapi/paths/management/oauth.yaml Adds 12 new endpoint definitions (RFC 7591 registration, OAuth 2.1 authorize/token, upstream proxy, consent flow pages, discovery endpoints) with complete request/response documentation
docs/changelogs/v1.5.0-prerelease2.mdx Adds model alias feature entry, 3 new breaking changes table (BC #9–11), and per-module changelog entries for core, framework, and HTTP transport
docs/openapi/openapi.yaml Correctly registers all 12 new per-user OAuth path references in three logical groups (Authorization Server, Consent Flow, Discovery)
docs/openapi/openapi.json Auto-generated JSON bundle — includes all new per-user OAuth endpoints and schemas consistent with the YAML source
docs/mcp/connecting-to-servers.mdx Updates connection type table and sections to mention per-user OAuth support for HTTP and SSE connections, with correct cross-references
docs/mcp/gateway-url.mdx Adds a short section explaining how the /mcp endpoint advertises OAuth support via WWW-Authenticate headers when per_user_oauth is configured
docs/mcp/oauth.mdx Adds an Info callout at the top to differentiate server-level OAuth from per-user OAuth, with a cross-reference link
docs/mcp/overview.mdx Adds a Per-User OAuth card to the MCP overview navigation section
docs/docs.json Adds per-user-oauth page to the MCP sidebar navigation

Comments Outside Diff (2)

  1. docs/openapi/schemas/management/mcp.yaml, line 86-91 (link)

    P2 oauth_config_id description excludes per_user_oauth

    The description says oauth_config_id is "Only relevant when auth_type is 'oauth'", but per-user-oauth.mdx explicitly documents that oauth_config_id is also required when auth_type is per_user_oauth (the ID of the OAuth credentials created during UI setup). This same stale description appears in at least two other places in this file (around lines 196–201 and 297–302).

  2. docs/openapi/schemas/management/mcp.yaml, line 3-11 (link)

    P2 per_user_oauth description says "OAuth 2.0" instead of "OAuth 2.1"

    The MCPAuthType description here labels per_user_oauth as "OAuth 2.0", but the rest of the PR — the oauth.yaml schema, the path definitions, and per-user-oauth.mdx — consistently call it OAuth 2.1. The path comments even cite specific OAuth 2.1 RFCs (RFC 7636 for PKCE, RFC 7591 for Dynamic Client Registration). The description on line 11 should read Per-user OAuth 2.1 authentication (each user authenticates individually) to match.

Reviews (1): Last reviewed commit: "docs: adds docs for per user mcp oauth" | Re-trigger Greptile

Comment thread docs/mcp/per-user-oauth.mdx
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (3)
docs/openapi/openapi.json (3)

32205-32245: Consider adding 404 response for DELETE endpoint.

The GET operation on this path documents a 404 response for "OAuth config not found", but the DELETE operation only documents 200 and 500. If a caller attempts to revoke a non-existent config, the expected behavior should be documented.

Suggested addition for DELETE responses
         "responses": {
           "200": {
             "description": "OAuth token revoked successfully",
             ...
           },
+          "404": {
+            "description": "OAuth config not found",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/ManagementErrorResponse"
+                }
+              }
+            }
+          },
           "500": {
             "description": "Internal server error",
             ...
           }
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/openapi/openapi.json` around lines 32205 - 32245, The DELETE operation
(operationId revokeOAuthConfig) is missing a 404 response; add a 404 entry under
"responses" for the revokeOAuthConfig operation documenting "OAuth config not
found" and reuse the same error schema used elsewhere (e.g., "$ref":
"#/components/schemas/BifrostError") so callers know revocation can return Not
Found—mirror the GET path's 404 style and content for consistency.

32336-32386: Response schema missing required array.

The 201 response schema for dynamic client registration defines properties but doesn't specify which are guaranteed in the response. Per RFC 7591, at minimum client_id is always returned. Adding a required array helps API consumers know which fields to expect.

Suggested addition
             "schema": {
               "type": "object",
               "description": "Dynamic Client Registration response per RFC 7591",
+              "required": [
+                "client_id"
+              ],
               "properties": {
                 "client_id": {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/openapi/openapi.json` around lines 32336 - 32386, The response schema
object for the Dynamic Client Registration response (the object that defines
properties like client_id, client_name, redirect_uris, grant_types,
response_types, token_endpoint_auth_method) is missing a required array; add a
"required" array to that schema and include at minimum "client_id" (per RFC
7591) and any other fields that are always returned by your implementation
(e.g., add "client_id" and optionally "client_name", "redirect_uris" if always
present) so API consumers know which fields are guaranteed in the 201 response.

32697-32725: Clarify mutual exclusivity of flow_id and session parameters.

Both parameters are marked as required: false, but the description states one is required depending on the flow type. Consider adding a note at the endpoint level or in each parameter description to clarify this mutual exclusivity constraint.

Suggested description enhancement
           {
             "name": "flow_id",
             "in": "query",
             "required": false,
-            "description": "Pending consent flow ID. Required if `session` is not provided.\nThe `__bifrost_flow_secret` cookie must be present and match the flow.\n",
+            "description": "Pending consent flow ID. **Mutually exclusive with `session`** — exactly one must be provided.\nThe `__bifrost_flow_secret` cookie must be present and match the flow.\n",
             "schema": {
               "type": "string"
             }
           },
           {
             "name": "session",
             "in": "query",
             "required": false,
-            "description": "Bifrost session ID (from the token endpoint). Required if `flow_id` is not provided.\nUsed for runtime (post-consent) upstream authorization.\n",
+            "description": "Bifrost session ID (from the token endpoint). **Mutually exclusive with `flow_id`** — exactly one must be provided.\nUsed for runtime (post-consent) upstream authorization.\n",
             "schema": {
               "type": "string"
             }
           }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/openapi/openapi.json` around lines 32697 - 32725, Update the OpenAPI
operation that declares the query parameters mcp_client_id, flow_id, and session
to clarify that flow_id and session are mutually exclusive and that one of them
is required depending on flow type: either add a concise sentence to each
parameter's description (e.g., "Mutually exclusive with `session`; one of
`flow_id` or `session` must be provided.") and/or add an endpoint-level
description or OpenAPI validation using oneOf/anyOf to enforce that exactly one
of `flow_id` or `session` is supplied; keep mcp_client_id as required. Reference
the parameter names mcp_client_id, flow_id, and session when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/changelogs/v1.5.0-prerelease2.mdx`:
- Line 58: Replace the concatenated token "prerelease1" in the changelog
sentence with the spaced, readable form "prerelease 1" (i.e., change the phrase
"prerelease1" to "prerelease 1" in the sentence referencing prerelease1) to
improve prose consistency and readability throughout the v1.5.0-prerelease2
release notes.

In `@docs/mcp/connecting-to-servers.mdx`:
- Around line 53-57: Update the contradictory wording so OAuth 2.0 is
consistently described as admin-managed/shared: find occurrences of the phrase
"user-based authentication" (or similar) that refer to OAuth 2.0 and change them
to "admin-managed/shared token (OAuth 2.0)" or "admin-shared OAuth 2.0 token,"
and ensure "OAuth 2.0" and "Per-User OAuth" sections clearly differentiate
admin-shared vs per-user flows (adjust headings/sentences that mention
"user-based authentication" to reference admin management instead).

In `@docs/openapi/paths/management/oauth.yaml`:
- Around line 354-386: The OpenAPI docs expose the long-lived Bifrost session ID
as the query parameter "session", which leaks a bearer credential; replace this
with a short-lived opaque handoff id (e.g., "handoff_id" or "runtime_handoff")
and update the parameter block and description accordingly: remove or deprecate
the "session" parameter, add a new required/optional query parameter
"handoff_id" used only for runtime post-consent authorization, describe that it
is short-lived and single-use (server-issued by the token endpoint), and ensure
the docs reference the existing "flow_id" behavior (and the
__bifrost_flow_secret cookie) so callers know to use flow_id OR handoff_id but
never the actual session token.
- Around line 559-564: The OpenAPI OAuth endpoint currently accepts a
self-declared user_id and links it to the pending flow, which enables
impersonation; change the contract so the endpoint no longer accepts an
arbitrary persistent user_id from the public browser form but instead either (a)
require a verifiable identity source (e.g., an authenticated principal or an
upstream trusted header like X-Bf-User-Id) before persisting the ID and storing
upstream tokens, or (b) scope the submitted user_id to the browser session only
(do not persist or reuse across gateways). Update the endpoint parameter/schema
for user_id and the flow that persists tokens to enforce one of these options
and add validation checks that reject unauthenticated/self-declared persistent
IDs.
- Around line 111-123: The MCP handler currently only handles req.AuthType ==
"oauth" and doesn't support the docs' per_user_oauth flow; update the MCP
request handling (the handler around the MCP request logic that inspects
req.AuthType) to also recognize "per_user_oauth" and route it to the same OAuth
registration logic (so the operationId registerPerUserOAuthClient in the OpenAPI
can be satisfied), or alternatively make the handler return 404 for
"per_user_oauth" and update the OpenAPI docs to remove/register that operation;
adjust the conditional that checks req.AuthType (the `if req.AuthType ==
"oauth"` branch) to include the "per_user_oauth" case and ensure the existing
OAuth client-registration code path is invoked or a clear 404 is returned when
not configured.

In `@docs/openapi/schemas/management/oauth.yaml`:
- Around line 207-225: PerUserOAuthTokenResponse currently marks core fields
optional; update the OpenAPI schema (PerUserOAuthTokenResponse) to add a
required array including access_token, token_type, and expires_in, and constrain
token_type to a fixed value (e.g., enum: ["Bearer"]) so generated clients always
receive/expect those fields and the token_type is validated as "Bearer"; ensure
descriptions/examples remain unchanged for access_token, token_type, expires_in,
and scope.
- Around line 5-11: The OpenAPI enum advertises an unsupported auth type; either
remove "per_user_oauth" from the enum or implement it end-to-end: add the
MCPAuthTypePerUserOauth constant in core/schemas/mcp.go, update the
MCPClientConfig.HttpHeaders() switch to handle the new MCPAuthTypePerUserOauth
case (return appropriate headers or behavior for per-user OAuth), and add the
corresponding value/handling in the database schema code in
framework/configstore/tables/mcp.go so the DB can store and round-trip this
enum; ensure any related serialization/deserialization and docs are updated to
match.

---

Nitpick comments:
In `@docs/openapi/openapi.json`:
- Around line 32205-32245: The DELETE operation (operationId revokeOAuthConfig)
is missing a 404 response; add a 404 entry under "responses" for the
revokeOAuthConfig operation documenting "OAuth config not found" and reuse the
same error schema used elsewhere (e.g., "$ref":
"#/components/schemas/BifrostError") so callers know revocation can return Not
Found—mirror the GET path's 404 style and content for consistency.
- Around line 32336-32386: The response schema object for the Dynamic Client
Registration response (the object that defines properties like client_id,
client_name, redirect_uris, grant_types, response_types,
token_endpoint_auth_method) is missing a required array; add a "required" array
to that schema and include at minimum "client_id" (per RFC 7591) and any other
fields that are always returned by your implementation (e.g., add "client_id"
and optionally "client_name", "redirect_uris" if always present) so API
consumers know which fields are guaranteed in the 201 response.
- Around line 32697-32725: Update the OpenAPI operation that declares the query
parameters mcp_client_id, flow_id, and session to clarify that flow_id and
session are mutually exclusive and that one of them is required depending on
flow type: either add a concise sentence to each parameter's description (e.g.,
"Mutually exclusive with `session`; one of `flow_id` or `session` must be
provided.") and/or add an endpoint-level description or OpenAPI validation using
oneOf/anyOf to enforce that exactly one of `flow_id` or `session` is supplied;
keep mcp_client_id as required. Reference the parameter names mcp_client_id,
flow_id, and session when making the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fb126029-9b1e-46e1-8cfa-f55481353b0c

📥 Commits

Reviewing files that changed from the base of the PR and between 7703aec and d6f9c40.

⛔ Files ignored due to path filters (7)
  • docs/media/ui-mcp-per-user-oauth-consent-identity.png is excluded by !**/*.png
  • docs/media/ui-mcp-per-user-oauth-consent-mcps.png is excluded by !**/*.png
  • docs/media/ui-mcp-per-user-oauth-flow-llm.svg is excluded by !**/*.svg
  • docs/media/ui-mcp-per-user-oauth-flow-mcp.svg is excluded by !**/*.svg
  • docs/media/ui-mcp-per-user-oauth-llm-prompt-llm.png is excluded by !**/*.png
  • docs/media/ui-mcp-per-user-oauth-llm-prompt-mcp.png is excluded by !**/*.png
  • docs/media/ui-mcp-per-user-oauth-setup.png is excluded by !**/*.png
📒 Files selected for processing (11)
  • docs/changelogs/v1.5.0-prerelease2.mdx
  • docs/docs.json
  • docs/mcp/connecting-to-servers.mdx
  • docs/mcp/gateway-url.mdx
  • docs/mcp/oauth.mdx
  • docs/mcp/overview.mdx
  • docs/mcp/per-user-oauth.mdx
  • docs/openapi/openapi.json
  • docs/openapi/openapi.yaml
  • docs/openapi/paths/management/oauth.yaml
  • docs/openapi/schemas/management/oauth.yaml

Comment thread docs/changelogs/v1.5.0-prerelease2.mdx
Comment thread docs/mcp/connecting-to-servers.mdx
Comment thread docs/openapi/paths/management/oauth.yaml
Comment thread docs/openapi/paths/management/oauth.yaml
Comment thread docs/openapi/paths/management/oauth.yaml
Comment thread docs/openapi/schemas/management/oauth.yaml
Comment thread docs/openapi/schemas/management/oauth.yaml
Copy link
Copy Markdown
Contributor

akshaydeo commented Apr 9, 2026

Merge activity

  • Apr 9, 5:50 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Apr 9, 5:51 PM UTC: @akshaydeo merged this pull request with Graphite.

@akshaydeo akshaydeo merged commit 8fbb190 into main Apr 9, 2026
17 of 19 checks passed
@akshaydeo akshaydeo deleted the 04-09-docs_adds_docs_for_per_user_mcp_oauth branch April 9, 2026 17:51
Vaibhav701161 pushed a commit to Vaibhav701161/bifrost that referenced this pull request Apr 11, 2026
## Summary

Adds comprehensive per-user OAuth 2.1 support for MCP clients, enabling each end-user to authenticate with upstream services (Notion, GitHub, etc.) using their own credentials instead of shared admin tokens. Also introduces a unified model alias system to map model names to provider-specific identifiers.

## Changes

- **Per-User OAuth Implementation**: Complete OAuth 2.1 authorization server with dynamic client registration (RFC 7591), PKCE support (RFC 7636), and OAuth discovery (RFC 8414, RFC 9728)
- **Consent Flow**: Multi-step browser-based consent system allowing users to select identity (Virtual Key, User ID, or session-only) and connect upstream services
- **Cross-Gateway Token Sharing**: Tokens stored against persistent identities work across both MCP Gateway and LLM Gateway
- **Lazy Authentication**: Runtime auth for services skipped during consent, with auth URLs returned in tool results
- **Model Alias System**: Unified top-level `aliases` field replacing provider-specific `deployments` configurations
- **Breaking Changes**: Provider `deployments` removed, Go SDK field renames for model tracking
- **Documentation**: Comprehensive guides for per-user OAuth setup, flows, and migration

## Type of change

- [x] Feature
- [ ] Bug fix
- [ ] Refactor
- [x] Documentation
- [ ] Chore/CI

## Affected areas

- [x] Core (Go)
- [x] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [x] UI (Next.js)
- [x] Docs

## How to test

### Per-User OAuth Flow
```sh
# 1. Configure an MCP client with per_user_oauth via Web UI
# 2. Test MCP client connection (Claude Code, Cursor)
curl -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -d '{"method": "tools/list"}'
# Should return 401 with WWW-Authenticate header

# 3. Test OAuth discovery
curl http://localhost:8080/.well-known/oauth-protected-resource
curl http://localhost:8080/.well-known/oauth-authorization-server

# 4. Test dynamic client registration
curl -X POST http://localhost:8080/api/oauth/per-user/register \
  -H "Content-Type: application/json" \
  -d '{"client_name":"Test","redirect_uris":["http://localhost:3000/callback"]}'
```

### Model Aliases
```sh
# Test alias resolution in chat completions
curl -X POST http://localhost:8080/v1/chat/completions \
  -H "Authorization: Bearer vk_your_key" \
  -H "Content-Type: application/json" \
  -d '{"model":"my-custom-alias","messages":[{"role":"user","content":"test"}]}'
```

### Core/Transports
```sh
go version
go test ./...
```

### UI
```sh
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```

## Screenshots/Recordings

- Identity selection screen for consent flow
- MCP services connection interface
- Per-user OAuth setup in Web UI
- Auth URL presentation in Claude Code and LLM responses

## Breaking changes

- [x] Yes
- [ ] No

**Breaking Changes in v1.5.0-prerelease2:**

1. **Provider `deployments` removed** - Azure, Bedrock, Vertex, and Replicate deployment maps must migrate to the unified top-level `aliases` field
2. **Go SDK: `ExtraFields.ModelRequested`** replaced by `OriginalModelRequested` + `ResolvedModelUsed`  
3. **Go SDK: `StreamAccumulatorResult.Model`** replaced by `RequestedModel` + `ResolvedModel`

See the [v1.5.0 Migration Guide](/migration-guides/v1.5.0) for full before/after examples and automatic migration details.

## Related issues

Implements per-user OAuth authentication for MCP clients and introduces unified model aliasing system.

## Security considerations

- **PKCE Required**: All OAuth flows require PKCE with S256 method for security
- **Browser Binding**: HttpOnly SameSite=Lax cookies prevent CSRF attacks during consent flows
- **Token Isolation**: Per-user tokens are scoped to individual identities with no cross-user access
- **Session Management**: 24-hour session tokens with automatic cleanup of expired flows/codes
- **Identity Validation**: Virtual Keys validated against database; User IDs are self-declared following existing trust model

## Checklist

- [x] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [x] I verified the CI pipeline passes locally if applicable
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants