Skip to content

ui: add OAuth2 consent page and MCP server auth mode settings - #4510

Merged
Pratham-Mishra04 merged 1 commit into
devfrom
06-18-feat_adds_ui_for_mcp_oauth_consent_screen
Jun 30, 2026
Merged

ui: add OAuth2 consent page and MCP server auth mode settings#4510
Pratham-Mishra04 merged 1 commit into
devfrom
06-18-feat_adds_ui_for_mcp_oauth_consent_screen

Conversation

@Pratham-Mishra04

Copy link
Copy Markdown
Collaborator

Summary

Adds an OAuth2 consent page and supporting configuration to allow MCP clients (e.g. claude mcp add) to authenticate via a browser-based OAuth flow. Anonymous visitors arrive at /oauth/consent?flow=<id> with a short-lived temp token embedded in the URL fragment, choose how they want to identify themselves (signed-in user, virtual key, or anonymous session), and are redirected back to the MCP client with an authorization code.

Changes

  • /oauth/consent route — New standalone page (layout.tsx + page.tsx) that renders outside the dashboard chrome. It wraps itself with ThemeProvider, ReduxProvider, NuqsAdapter, and Toaster directly since it does not inherit them from ClientLayout. TempTokenScope extracts the #t=… fragment and attaches it as X-Bifrost-Temp-Token on every API call so the consent APIs can authenticate the anonymous visitor.
  • Consent UIConsentView fetches the flow details and presents up to three authentication options: continuing as the signed-in user, entering a virtual key, or proceeding anonymously. It preserves the temp token across the login redirect via sessionStorage so users who choose to sign in are returned to the correct flow.
  • oauth2ConsentApi — New RTK Query endpoints (GET and PUT /oauth2/consent/flows/:flowId) for fetching flow details and submitting the chosen identity mode.
  • MCP Server Auth Mode setting — The MCP config view gains a mcp_server_auth_mode selector (headers / both / oauth) with contextual warnings: switching to oauth disables VK/header access; downgrading back to headers revokes all existing OAuth JWTs. OAuth2 server settings (issuer URL, auth code TTL, access token TTL) are revealed when the mode is both or oauth.
  • CoreConfig types — Added mcp_server_auth_mode and oauth2_server_config (issuer URL, auth code TTL, access token TTL) to the config type and dirty-check logic.
  • loginGoto/oauth/consent is now treated as a valid post-login redirect destination.

Type of change

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

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (React)
  • Docs

How to test

  1. Start Bifrost with an MCP server configured.
  2. Run claude mcp add --transport sse <bifrost-url>/mcp (or equivalent). The client should redirect to /oauth/consent?flow=<id>#t=<token>.
  3. Verify the consent page loads without requiring a dashboard login.
  4. Test each identity mode:
    • User — sign in via the login redirect and confirm you are returned to the consent page and redirected back to the MCP client.
    • Virtual key — enter a valid sk-bf-… key and confirm a successful redirect.
    • Anonymous — click "Continue without an identity" and confirm a successful redirect.
  5. In the MCP config view, toggle mcp_server_auth_mode between headers, both, and oauth and verify the correct warnings appear and the OAuth2 server settings section shows/hides accordingly.
cd ui
pnpm i
pnpm build

Breaking changes

  • Yes
  • No

Setting mcp_server_auth_mode to oauth disables virtual key and header-based MCP authentication immediately. All existing MCP integrations using VK, api-key, or session headers will stop working until clients re-authenticate via the OAuth consent flow. Setting the mode back to headers from both or oauth invalidates all previously issued OAuth JWTs and refresh tokens.

Security considerations

  • The temp token (#t=…) is passed in the URL fragment and never sent to the server by the browser directly; it is extracted client-side and attached as a custom header (X-Bifrost-Temp-Token), limiting exposure in server logs.
  • setSuppressGlobal401 is called when restoring a temp token from sessionStorage after a login redirect to prevent the global 401 handler from clearing the session prematurely during the consent flow.
  • The consent page is intentionally accessible without a dashboard session; all authorization is enforced server-side via the flow ID and temp token.

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

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

Pratham-Mishra04 commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@Pratham-Mishra04, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 7 minutes and 15 seconds. Learn how PR review limits work.

To continue reviewing without waiting, enable usage-based billing in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4adefcd6-90db-44c1-af67-df25f1b24ab6

📥 Commits

Reviewing files that changed from the base of the PR and between 3ab71d6 and 0764784.

📒 Files selected for processing (3)
  • ui/app/oauth/consent/layout.tsx
  • ui/app/oauth/consent/page.tsx
  • ui/app/workspace/config/views/mcpView.tsx
📝 Walkthrough

Walkthrough

Adds a new /oauth/consent route with temp-token scoping, an RTK Query API module for fetching and submitting OAuth2 consent flows, and a full consent page UI with mode selection and sessionStorage token restore. Also extends CoreConfig and the MCP settings view with mcp_server_auth_mode and oauth2_server_config fields including a new Advanced Settings auth UI section.

Changes

OAuth2 Consent Page

Layer / File(s) Summary
OAuth2 consent API contracts and RTK Query endpoints
ui/lib/store/apis/oauth2ConsentApi.ts, ui/lib/store/apis/index.ts
Defines OAuth2ConsentFlowDetail, OAuth2ConsentSubmitRequest, OAuth2ConsentSubmitResponse interfaces, wires getOAuth2ConsentFlow query and submitOAuth2ConsentFlow PUT mutation into baseApi, exports generated hooks, and re-exports through the apis barrel.
Route layout, temp-token scoping, and navigation whitelist
ui/app/oauth/consent/layout.tsx, ui/lib/utils/loginGoto.ts
Creates the /oauth/consent TanStack Router route wrapping OAuth2ConsentPage in providers and TempTokenScope with staticData.tempTokenScoped: true, and extends isWorkspaceRoute to accept /oauth/consent as a valid goto destination.
Consent page UI: mode selection, token restore, submit, and error views
ui/app/oauth/consent/page.tsx
Implements OAuth2ConsentPage reading the flow query param, fetching flow data, restoring a temp token from sessionStorage, rendering user/vk/session mode options, submitting with redirect on success and toast on error; also adds formatExpiry, Shell layout wrapper, and InvalidLinkView for 401 errors.

MCP Server Authentication Configuration

Layer / File(s) Summary
CoreConfig OAuth2 and auth mode type extensions
ui/lib/types/config.ts
Adds optional mcp_server_auth_mode ("headers" | "both" | "oauth") and optional oauth2_server_config object (issuer_url, auth_code_ttl, access_token_ttl) to the CoreConfig interface.
MCP view: change detection, handlers, and auth mode UI
ui/app/workspace/config/views/mcpView.tsx
Expands hasChanges to track the new auth fields, adds handlers for mcp_server_auth_mode, issuer_url, and numeric TTL inputs with positive-number validation, and renders an Advanced Settings auth mode selector with a conditional "OAuth2 Server Settings" form section.

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant OAuth2ConsentPage
  participant sessionStorage
  participant oauth2ConsentApi as RTK Query (oauth2ConsentApi)

  Browser->>OAuth2ConsentPage: GET /oauth/consent?flow=flowId
  OAuth2ConsentPage->>sessionStorage: restore temp token keyed by flowId
  OAuth2ConsentPage->>oauth2ConsentApi: getOAuth2ConsentFlow(flowId)
  oauth2ConsentApi-->>OAuth2ConsentPage: OAuth2ConsentFlowDetail (modes, expires_at)
  OAuth2ConsentPage->>OAuth2ConsentPage: render user / vk / session mode selection
  OAuth2ConsentPage->>oauth2ConsentApi: submitOAuth2ConsentFlow({ mode, value })
  oauth2ConsentApi-->>OAuth2ConsentPage: { redirect_url }
  OAuth2ConsentPage->>Browser: window.location = redirect_url
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

  • maximhq/bifrost#3467: This PR's new e2e tests exercise the OAuth/OAuth2 popup authorization flows that rely on the consent UI and API added in the main PR.
  • maximhq/bifrost#3603: Main PR's new /oauth/consent frontend route and page leverage the temp-token mechanism (via TempTokenScope, X-Bifrost-Temp-Token, and global-401 suppression) that the retrieved PR adds server-side.

Suggested reviewers

  • akshaydeo
  • danpiths

🐇 A consent page hops into view,
With tokens restored and modes to pursue!
OAuth flows submit and redirect with flair,
MCP auth modes now open—the bunny's right there! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main changes: adding an OAuth2 consent page and MCP server auth mode settings to the UI.
Description check ✅ Passed The description is comprehensive and follows the template structure with all major sections populated: Summary, Changes, Type of change, Affected areas, How to test, Breaking changes, Security considerations, and Checklist.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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 06-18-feat_adds_ui_for_mcp_oauth_consent_screen

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

@coderabbitai
coderabbitai Bot requested a review from roroghost17 June 17, 2026 21:13
@greptile-apps

greptile-apps Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 5/5

Safe to merge; the consent page and MCP auth-mode config are self-contained UI additions with no regressions on existing flows.

All previously raised concerns have been addressed: sessionStorage restore runs inside the useState initializer, the sessionStorage write is a useEffect, redirect URLs are validated with isSafeRedirect, TTL inputs are controlled, TTL validation is guarded by auth mode, and the clientConfigToSave merge ensures TTL values are always included in the save payload. No new correctness or security issues were found.

No files require special attention.

Important Files Changed

Filename Overview
ui/app/oauth/consent/page.tsx New consent page with proper sessionStorage restore ordering, isSafeRedirect guard, controlled form state, and all three identity mode flows. All previously flagged issues are resolved.
ui/app/oauth/consent/layout.tsx Standalone TanStack Router route that self-hosts ThemeProvider, ReduxProvider, NuqsAdapter, Toaster, and TempTokenScope.
ui/app/workspace/config/views/mcpView.tsx Adds MCP server auth mode selector with controlled TTL inputs, OAuth-mode-guarded validation, secretVarEquals dirty-check for issuer URL, and clientConfigToSave merge before save.
ui/lib/store/apis/oauth2ConsentApi.ts RTK Query endpoints for GET and PUT /oauth2/consent/flows/:flowId with correct flowId URL-encoding.
ui/lib/types/config.ts Adds mcp_server_auth_mode and oauth2_server_config to CoreConfig, aligned with the config schema.
ui/lib/utils/loginGoto.ts isWorkspaceRoute now explicitly and narrowly allows /oauth/consent paths without matching /oauth/consentblah.
ui/lib/store/apis/index.ts Re-exports the new oauth2ConsentApi.

Reviews (28): Last reviewed commit: "feat: adds ui for mcp oauth consent scre..." | Re-trigger Greptile

Comment thread ui/app/oauth/consent/page.tsx
Comment thread ui/app/workspace/config/views/mcpView.tsx Outdated
Comment thread ui/app/workspace/config/views/mcpView.tsx Outdated
Comment thread ui/lib/utils/loginGoto.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ui/app/oauth/consent/page.tsx`:
- Around line 275-283: The formatExpiry function does not validate that the
parsed date is valid before using it in calculations. When an invalid ISO string
is passed, new Date(iso).getTime() returns NaN, which then gets propagated
through the arithmetic operations and renders as "in NaN minutes". Add a check
immediately after calculating diffMs to verify it is not NaN, and if it is NaN,
return a safe default value such as "soon" before proceeding with the remaining
logic.
- Around line 290-292: The inner div with the className containing "bg-card
w-1/3 rounded-sm border p-8 shadow-sm" uses a fixed width of w-1/3 which is not
responsive on mobile screens. Replace the w-1/3 class with a responsive width
approach that uses full width (w-full) on small screens and constrains the width
on larger screens. Consider using a combination of w-full with a max-width
constraint (such as max-w-sm or max-w-md) and add responsive breakpoint
modifiers (like md:w-1/3) to achieve the desired layout on different screen
sizes.
- Around line 149-264: Add data-testid attributes to all new interactive
controls in the consent flow to enable stable Playwright E2E test selectors.
Specifically, add data-testid to: the "Continue as" button that calls
handleSubmit("user"), the login link in the sign-in section, the virtual key
input field (id="vk-input"), the "Connect with key" button that calls
handleSubmit("vk"), and the "Continue without an identity" button that calls
handleSubmit("session"). Use descriptive, stable identifiers that clearly
indicate the purpose of each element to support E2E test coverage.
- Around line 134-265: The consent page currently renders nothing when no
authentication modes are available (when all conditions like hasUser, hasVK, and
hasSession evaluate to false). Add an empty state UI that displays when none of
the consent modes can be shown. This should check if no modes are available and
render a message informing the user that no authentication options are currently
available. Place this empty state within the space-y-3 div container,
conditional on the absence of all available modes (user mode, VK mode, and
session mode).

In `@ui/app/workspace/config/views/mcpView.tsx`:
- Around line 171-189: The validation in handleAuthCodeTTLChange and
handleAccessTokenTTLChange currently only checks if the parsed number is greater
than 0, but the input fields declare a minimum of 60 seconds. Update both
handlers to also enforce the minimum of 60 seconds by changing the condition
from num > 0 to num >= 60 when validating auth_code_ttl and access_token_ttl in
the oauth2_server_config. Additionally, add validation logic in the handleSave
function to check both TTL values against the 60-second minimum and display a
toast notification to the user if either value falls below the required minimum,
providing explicit feedback about the constraint.
- Around line 91-99: The issuer URL comparison only checks the .value property
of the EnvVar, missing changes to env_var and from_env fields. This prevents the
Save Changes button from being enabled when switching between literal values and
environment variables. Replace the direct comparison of issuer_url?.value with a
call to the envVarEquals function (reusing the same approach used for the
clientURLChanged comparison earlier in the condition chain) to properly compare
the full EnvVar object including all fields.

In `@ui/lib/store/apis/oauth2ConsentApi.ts`:
- Around line 22-30: The flowId parameter is being directly interpolated into
API endpoint paths without URL encoding in both the getOAuth2ConsentFlow and
submitOAuth2ConsentFlow methods. This allows reserved characters in the
user-controlled flowId to alter the requested route. Wrap the flowId with
encodeURIComponent() before inserting it into the URL paths for both the query
and mutation endpoints to ensure proper URL encoding.

In `@ui/lib/utils/loginGoto.ts`:
- Line 29: The value.startsWith("/oauth/consent") check in the loginGoto.ts file
is too permissive because it matches unintended paths like
"/oauth/consent-anything". Examine how the /workspace path checks are
implemented in the same file to understand the proper restriction pattern, then
apply the same approach to the /oauth/consent check to ensure it only matches
the intended paths (likely by checking for an exact match or verifying a path
separator follows the prefix).
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 3c974628-a163-403f-b346-da529229f20f

📥 Commits

Reviewing files that changed from the base of the PR and between 98169a4 and 3d76e6a.

📒 Files selected for processing (7)
  • ui/app/oauth/consent/layout.tsx
  • ui/app/oauth/consent/page.tsx
  • ui/app/workspace/config/views/mcpView.tsx
  • ui/lib/store/apis/index.ts
  • ui/lib/store/apis/oauth2ConsentApi.ts
  • ui/lib/types/config.ts
  • ui/lib/utils/loginGoto.ts

Comment thread ui/app/oauth/consent/page.tsx
Comment thread ui/app/oauth/consent/page.tsx
Comment thread ui/app/oauth/consent/page.tsx
Comment thread ui/app/oauth/consent/page.tsx Outdated
Comment thread ui/app/workspace/config/views/mcpView.tsx Outdated
Comment thread ui/app/workspace/config/views/mcpView.tsx
Comment thread ui/lib/store/apis/oauth2ConsentApi.ts Outdated
Comment thread ui/lib/utils/loginGoto.ts Outdated
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-17-feat_adds_mcp_oauth2_server_lifecycle_token_rotation_liveness_checks_sessions_api branch from 98169a4 to be01ec8 Compare June 18, 2026 07:34
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_adds_ui_for_mcp_oauth_consent_screen branch from 3d76e6a to e5a9a8f Compare June 18, 2026 07:34
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 18, 2026
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-17-feat_adds_mcp_oauth2_server_lifecycle_token_rotation_liveness_checks_sessions_api branch from be01ec8 to 9282613 Compare June 18, 2026 07:37
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_adds_ui_for_mcp_oauth_consent_screen branch from e5a9a8f to 47cce08 Compare June 18, 2026 07:37
Comment thread ui/app/workspace/config/views/mcpView.tsx
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_adds_ui_for_mcp_oauth_consent_screen branch from 47cce08 to 577e9c3 Compare June 18, 2026 08:17
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-17-feat_adds_mcp_oauth2_server_lifecycle_token_rotation_liveness_checks_sessions_api branch from 9282613 to 2a42dc9 Compare June 18, 2026 08:17
Comment thread ui/app/oauth/consent/page.tsx Outdated
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_adds_ui_for_mcp_oauth_consent_screen branch from 577e9c3 to 87046c1 Compare June 18, 2026 08:38
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-17-feat_adds_mcp_oauth2_server_lifecycle_token_rotation_liveness_checks_sessions_api branch from 2a42dc9 to 1c19dfb Compare June 18, 2026 08:38
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_adds_ui_for_mcp_oauth_consent_screen branch from 87046c1 to c6c30c4 Compare June 18, 2026 10:35
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-17-feat_adds_mcp_oauth2_server_lifecycle_token_rotation_liveness_checks_sessions_api branch from 1c19dfb to 0ecdc90 Compare June 18, 2026 10:35
Comment thread ui/app/workspace/config/views/mcpView.tsx
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_adds_ui_for_mcp_oauth_consent_screen branch from bcdf0a4 to 91ef58c Compare June 29, 2026 18:18
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-17-feat_adds_mcp_oauth2_server_lifecycle_token_rotation_liveness_checks_sessions_api branch from cc3e020 to 347b1b0 Compare June 29, 2026 18:18
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_adds_ui_for_mcp_oauth_consent_screen branch from 91ef58c to 90b5a4b Compare June 30, 2026 07:53
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-17-feat_adds_mcp_oauth2_server_lifecycle_token_rotation_liveness_checks_sessions_api branch from 347b1b0 to 8362a9e Compare June 30, 2026 07:53
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_adds_ui_for_mcp_oauth_consent_screen branch from 90b5a4b to ce55915 Compare June 30, 2026 11:43
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-17-feat_adds_mcp_oauth2_server_lifecycle_token_rotation_liveness_checks_sessions_api branch 2 times, most recently from 594fa59 to ec3bbac Compare June 30, 2026 13:44
@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_adds_ui_for_mcp_oauth_consent_screen branch from ce55915 to 520b193 Compare June 30, 2026 13:44

Pratham-Mishra04 commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator Author

Merge activity

  • Jun 30, 1:53 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jun 30, 2:11 PM UTC: Graphite rebased this pull request as part of a merge.
  • Jun 30, 2:12 PM UTC: @Pratham-Mishra04 merged this pull request with Graphite.

@Pratham-Mishra04
Pratham-Mishra04 changed the base branch from 06-17-feat_adds_mcp_oauth2_server_lifecycle_token_rotation_liveness_checks_sessions_api to graphite-base/4510 June 30, 2026 14:07
@Pratham-Mishra04
Pratham-Mishra04 changed the base branch from graphite-base/4510 to dev June 30, 2026 14:10
@Pratham-Mishra04
Pratham-Mishra04 dismissed coderabbitai[bot]’s stale review June 30, 2026 14:10

The base branch was changed.

@Pratham-Mishra04
Pratham-Mishra04 force-pushed the 06-18-feat_adds_ui_for_mcp_oauth_consent_screen branch from 520b193 to 47ea665 Compare June 30, 2026 14:10
@Pratham-Mishra04
Pratham-Mishra04 merged commit e379e66 into dev Jun 30, 2026
15 of 16 checks passed
@Pratham-Mishra04
Pratham-Mishra04 deleted the 06-18-feat_adds_ui_for_mcp_oauth_consent_screen branch June 30, 2026 14:12
akshaydeo pushed a commit that referenced this pull request Jul 1, 2026
## Summary

Adds an OAuth2 consent page and supporting configuration to allow MCP clients (e.g. `claude mcp add`) to authenticate via a browser-based OAuth flow. Anonymous visitors arrive at `/oauth/consent?flow=<id>` with a short-lived temp token embedded in the URL fragment, choose how they want to identify themselves (signed-in user, virtual key, or anonymous session), and are redirected back to the MCP client with an authorization code.

## Changes

- **`/oauth/consent` route** — New standalone page (`layout.tsx` + `page.tsx`) that renders outside the dashboard chrome. It wraps itself with `ThemeProvider`, `ReduxProvider`, `NuqsAdapter`, and `Toaster` directly since it does not inherit them from `ClientLayout`. `TempTokenScope` extracts the `#t=…` fragment and attaches it as `X-Bifrost-Temp-Token` on every API call so the consent APIs can authenticate the anonymous visitor.
- **Consent UI** — `ConsentView` fetches the flow details and presents up to three authentication options: continuing as the signed-in user, entering a virtual key, or proceeding anonymously. It preserves the temp token across the login redirect via `sessionStorage` so users who choose to sign in are returned to the correct flow.
- **`oauth2ConsentApi`** — New RTK Query endpoints (`GET` and `PUT` `/oauth2/consent/flows/:flowId`) for fetching flow details and submitting the chosen identity mode.
- **MCP Server Auth Mode setting** — The MCP config view gains a `mcp_server_auth_mode` selector (`headers` / `both` / `oauth`) with contextual warnings: switching to `oauth` disables VK/header access; downgrading back to `headers` revokes all existing OAuth JWTs. OAuth2 server settings (issuer URL, auth code TTL, access token TTL) are revealed when the mode is `both` or `oauth`.
- **`CoreConfig` types** — Added `mcp_server_auth_mode` and `oauth2_server_config` (issuer URL, auth code TTL, access token TTL) to the config type and dirty-check logic.
- **`loginGoto`** — `/oauth/consent` is now treated as a valid post-login redirect destination.

## Type of change

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

## Affected areas

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

## How to test

1. Start Bifrost with an MCP server configured.
2. Run `claude mcp add --transport sse <bifrost-url>/mcp` (or equivalent). The client should redirect to `/oauth/consent?flow=<id>#t=<token>`.
3. Verify the consent page loads without requiring a dashboard login.
4. Test each identity mode:
   - **User** — sign in via the login redirect and confirm you are returned to the consent page and redirected back to the MCP client.
   - **Virtual key** — enter a valid `sk-bf-…` key and confirm a successful redirect.
   - **Anonymous** — click "Continue without an identity" and confirm a successful redirect.
5. In the MCP config view, toggle `mcp_server_auth_mode` between `headers`, `both`, and `oauth` and verify the correct warnings appear and the OAuth2 server settings section shows/hides accordingly.

```sh
cd ui
pnpm i
pnpm build
```

## Breaking changes

- [x] Yes
- [ ] No

Setting `mcp_server_auth_mode` to `oauth` disables virtual key and header-based MCP authentication immediately. All existing MCP integrations using VK, api-key, or session headers will stop working until clients re-authenticate via the OAuth consent flow. Setting the mode back to `headers` from `both` or `oauth` invalidates all previously issued OAuth JWTs and refresh tokens.

## Security considerations

- The temp token (`#t=…`) is passed in the URL fragment and never sent to the server by the browser directly; it is extracted client-side and attached as a custom header (`X-Bifrost-Temp-Token`), limiting exposure in server logs.
- `setSuppressGlobal401` is called when restoring a temp token from `sessionStorage` after a login redirect to prevent the global 401 handler from clearing the session prematurely during the consent flow.
- The consent page is intentionally accessible without a dashboard session; all authorization is enforced server-side via the flow ID and temp token.

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

2 participants