fix: surface context-aware rejection message when inbound bearer token is rejected during delegated exchange - #7051
Conversation
…efusals and stop rendering an empty authorize URL
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
|
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (6)
Included review availability: Your plan provides up to 10 included reviews per hour; 5 remain after this review. 📝 SummarySummary by CodeRabbit
WalkthroughThe 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. ChangesMCP authentication guidance
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
Merge Risk: ⚪ Minimal · up to 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)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Comment |

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
MCPInboundBearerOmittedReasontype andMCPInboundBearerRejectedconstant tocore/schemas/mcp.goto represent why an inbound bearer token was not forwarded to token exchange.BifrostContextKeyMCPInboundBearerOmittedcontext key tocore/schemas/bifrost.goso the upstream auth layer can record a token rejection for downstream use.token_exchange.gowithsubjectTokenMissingMessage, 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.mcpAuthRequiredToolResultinmcpserver.goto 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.token_exchange_test.goand the full set of tool-result formatting cases in the newmcpserver_toolresult_test.go.Type of change
Affected areas
How to test
go test ./core/mcp/credstore/... ./transports/bifrost-http/handlers/...Breaking changes
Security considerations
BifrostContextKeyMCPInboundBearerOmittedrecords only the reason string ("rejected"), not the token itself. The existingBifrostContextKeyMCPInboundBearerkey, which holds the live credential, is unchanged and must never be logged.Checklist
docs/contributing/README.mdand followed the guidelines