Skip to content

fix: surface context-aware rejection message when inbound bearer token is rejected during delegated exchange - #7051

Open
Pratham-Mishra04 wants to merge 1 commit into
09-10-docs_add_the_profile-less_user_refusal_to_the_enterprise_v2.1.0_breaking_changesfrom
09-10-fix_name_why_no_identity_token_was_available_in_mcp_token-exchange_refusals_and_stop_rendering_an_empty_authorize_url
Open

fix: surface context-aware rejection message when inbound bearer token is rejected during delegated exchange#7051
Pratham-Mishra04 wants to merge 1 commit into
09-10-docs_add_the_profile-less_user_refusal_to_the_enterprise_v2.1.0_breaking_changesfrom
09-10-fix_name_why_no_identity_token_was_available_in_mcp_token-exchange_refusals_and_stop_rendering_an_empty_authorize_url

Conversation

@Pratham-Mishra04

Copy link
Copy Markdown
Collaborator

Summary

When a token-exchange MCP server rejects a request because no subject token was available, the error message now distinguishes between two distinct situations: the caller never sent an identity-provider token, versus the caller sent one that failed validation. Previously, both cases produced the same generic "send a token" message, which is unhelpful to a caller who already sent a token and had it rejected.

Additionally, the tool-result message for auth-required errors is refactored so that delegated exchange errors (which have no interactive URL to open) pass through the resolver's own message directly, rather than prompting the caller to open an empty URL.

Changes

  • Added MCPInboundBearerOmittedReason type and MCPInboundBearerRejected constant to core/schemas/mcp.go to represent why an inbound bearer token was not forwarded to token exchange.
  • Added BifrostContextKeyMCPInboundBearerOmitted context key to core/schemas/bifrost.go so the upstream auth layer can record a token rejection for downstream use.
  • Replaced the inline error message string in token_exchange.go with subjectTokenMissingMessage, which reads the context key and returns a rejection-specific message when the auth layer recorded a failed token, or a "please send one" message when no token was presented at all.
  • Extracted mcpAuthRequiredToolResult in mcpserver.go to handle all auth-required tool result formatting. Exchange errors with no URL now pass through the resolver's message directly; interactive kinds with no URL also fall back to their message rather than prompting the caller to open nothing.
  • Added tests covering the new message branching in token_exchange_test.go and the full set of tool-result formatting cases in the new mcpserver_toolresult_test.go.

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

go test ./core/mcp/credstore/... ./transports/bifrost-http/handlers/...
  • A request that carries no identity-provider token receives a message instructing it to send one as the Authorization bearer.
  • A request whose identity-provider token was rejected by the auth layer receives a message stating the token was rejected and advising the caller to re-authenticate with their identity provider.
  • A tool result for a delegated-exchange auth-required error carries the resolver's message and does not contain "Open this URL".
  • A tool result for an OAuth or headers auth-required error with a URL still contains the URL and the appropriate action phrase.
  • A tool result for an interactive kind with no URL falls back to the error's message field.

Breaking changes

  • Yes
  • No

Security considerations

BifrostContextKeyMCPInboundBearerOmitted records only the reason string ("rejected"), not the token itself. The existing BifrostContextKeyMCPInboundBearer key, which holds the live credential, is unchanged and must never be logged.

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

…efusals and stop rendering an empty authorize URL
@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

coderabbitai Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Team

Run ID: abef6d9f-60f8-4aa3-b8d6-0af71e87de74

📥 Commits

Reviewing files that changed from the base of the PR and between 1e75e68 and 7139594.

📒 Files selected for processing (6)
  • core/mcp/credstore/token_exchange.go
  • core/mcp/credstore/token_exchange_test.go
  • core/schemas/bifrost.go
  • core/schemas/mcp.go
  • transports/bifrost-http/handlers/mcpserver.go
  • transports/bifrost-http/handlers/mcpserver_toolresult_test.go

Included review availability: Your plan provides up to 10 included reviews per hour; 5 remain after this review.


📝 Summary

Summary by CodeRabbit

  • Bug Fixes
    • Improved authentication error messages for MCP tool requests.
    • Requests without an inbound identity token now receive instructions for providing one.
    • Rejected identity tokens now receive rejection-specific guidance instead of missing-token instructions.
    • Authentication-required responses now provide clearer guidance across OAuth, header-based, and delegated authentication flows.
    • Preserved temporary-token reminders and added fallback messaging when authentication details or URLs are unavailable.

Walkthrough

The change adds context metadata for inbound bearer-token omission reasons. Subject-token exchange errors now distinguish missing and rejected tokens. MCP tool authentication results use centralized formatting with coverage for OAuth, headers, delegated exchange, fallback messages, and temporary-token guidance.

Changes

MCP authentication guidance

Layer / File(s) Summary
Inbound bearer omission contract
core/schemas/bifrost.go, core/schemas/mcp.go
Adds the context key, reason type, and rejected-token constant used to record inbound bearer-token handling.
Subject-token error diagnostics
core/mcp/credstore/token_exchange.go, core/mcp/credstore/token_exchange_test.go
Uses the omission reason to return different messages for missing and rejected inbound bearer tokens. Tests verify both messages.
MCP tool authentication results
transports/bifrost-http/handlers/mcpserver.go, transports/bifrost-http/handlers/mcpserver_toolresult_test.go
Centralizes authentication-required result formatting for OAuth, header, delegated exchange, missing URLs, fallback text, and temporary-token reminders. Tests cover each path.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MCPToolExecution
  participant TokenExchange
  participant BifrostContext
  participant MCPClient
  MCPToolExecution->>TokenExchange: resolve subject token
  TokenExchange->>BifrostContext: read inbound bearer omission reason
  BifrostContext-->>TokenExchange: return missing or rejected reason
  TokenExchange-->>MCPToolExecution: return authentication guidance
  MCPToolExecution-->>MCPClient: return formatted authentication result
Loading

Merge Risk: ⚪ Minimal · up to 71395

MCP authentication errors now provide more accurate guidance for missing or rejected tokens while preserving interactive authorization and fallback messages. The change is mergeable with normal checks.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 6 files. 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 specifically describes the primary change: surfacing a context-aware message when an inbound bearer token is rejected during delegated exchange.
Description check ✅ Passed The description explains the problem, implementation, affected areas, testing steps, security considerations, and checklist status. The Screenshots/Recordings and Related issues sections are omitted, …
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.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 09-10-fix_name_why_no_identity_token_was_available_in_mcp_token-exchange_refusals_and_stop_rendering_an_empty_authorize_url

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

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