Skip to content

tests: add MCP auth e2e collection covering discovery, credential matrix, OAuth issuance, refresh rotation, revocation window, and runtime mode flip#4525

Open
Pratham-Mishra04 wants to merge 1 commit into
06-18-feat_adds_mcp_oauth_server_type_e2e_testsfrom
06-18-feat_mcp_oauth_server_e2e_tests
Open

tests: add MCP auth e2e collection covering discovery, credential matrix, OAuth issuance, refresh rotation, revocation window, and runtime mode flip#4525
Pratham-Mishra04 wants to merge 1 commit into
06-18-feat_adds_mcp_oauth_server_type_e2e_testsfrom
06-18-feat_mcp_oauth_server_e2e_tests

Conversation

@Pratham-Mishra04

Copy link
Copy Markdown
Collaborator

Summary

Adds a comprehensive end-to-end test suite for MCP inbound authentication, covering all three server auth modes (headers, both, oauth) in a single Postman collection driven by a dedicated Newman runner.

Changes

  • Added bifrost-v1-mcp-auth.postman_collection.json with five new test folders:
    • Config validation: asserts that unknown mcp_server_auth_mode values and oauth2_server_config payloads sent with headers mode are rejected with 400, and that the boot mode round-trips correctly through GET /api/config.
    • Full OAuth flow (virtual-key identity): covers dynamic client registration, PKCE-S256 authorize, consent bound to a virtual key, token exchange, JWT connect to /mcp, refresh rotation, and stolen-token family revocation (replaying a rotated refresh token revokes the entire grant family).
    • Revocation window: issues a fresh grant, revokes it via the management API, then asserts that the refresh token is immediately rejected while the already-issued short-lived access token continues to connect until expiry.
    • Full OAuth flow (session identity): consent mints a server-side session identity, the resulting JWT connects to /mcp, and then enabling enforce_auth_on_inference at runtime causes that same session token to be rejected.
    • Runtime config flip (headers → both): from a headers-mode boot, upgrades to both via PUT /api/config, confirms discovery endpoints come alive, and verifies header-VK connections are unaffected.
  • All test scripts branch on the auth_mode env-var so a single collection encodes the full credential matrix across modes; steps that do not apply to a given mode are skipped with a passing no-op assertion.
  • Added --ignore-redirects to the Newman invocation in run-newman-mcp-auth-tests.sh so that authorize redirects are captured as 302 responses rather than followed, allowing the collection to extract flow IDs from Location headers.
  • Updated README.md with a full description of the new collection and runner, including per-mode assertion summaries and local run instructions.

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

Run the MCP auth test suite locally from tests/e2e/api:

./runners/individual/run-newman-mcp-auth-tests.sh --binary /path/to/bifrost-http

# Optional flags
# --port <port>   (default 8090)
# --html          emit HTML report
# --json          emit JSON report
# --verbose       verbose Newman output
# --bail          stop on first failure

The runner builds and starts the upstream MCP server (examples/mcps/http-no-ping-server), boots a fresh server instance per mcp_server_auth_mode, pre-seeds an MCP client and two virtual keys (one active, one inactive), and executes the collection against each mode in sequence. A built bifrost-http binary is required.

Screenshots/Recordings

N/A

Breaking changes

  • Yes
  • No

Related issues

N/A

Security considerations

The collection exercises the full OAuth 2.0 issuance surface including PKCE, refresh rotation, stolen-token family revocation, and the revocation window. No secrets are introduced; all credentials are ephemeral test values seeded by the runner.

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 18, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai

coderabbitai Bot commented Jun 18, 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: 2452eed3-fca9-4446-96a2-c8446362809a

📥 Commits

Reviewing files that changed from the base of the PR and between fb2ee5f and 6071377.

📒 Files selected for processing (3)
  • tests/e2e/api/README.md
  • tests/e2e/api/collections/bifrost-v1-mcp-auth.postman_collection.json
  • tests/e2e/api/runners/individual/run-newman-mcp-auth-tests.sh
📝 Walkthrough

Walkthrough

Extends the MCP auth Postman collection with config validation, full OAuth virtual-key identity and session identity flows, revocation window tests, and a runtime config flip scenario. The Newman runner gains --ignore-redirects, and the README gains a new MCP Auth Tests documentation section.

Changes

MCP Auth E2E Test Suite Expansion

Layer / File(s) Summary
Newman runner flag and README documentation
tests/e2e/api/runners/individual/run-newman-mcp-auth-tests.sh, tests/e2e/api/README.md
Adds --ignore-redirects to newman run in the MCP auth runner and introduces a README section documenting the collection paths, per-mode boot strategy, per-mode acceptance/rejection expectations, and the local run command with options.
Config validation tests
tests/e2e/api/collections/bifrost-v1-mcp-auth.postman_collection.json
Adds a Config validation suite that PUTs invalid mcp_server_auth_mode and incompatible oauth2_server_config to /api/config (expecting 400), then round-trips a GET to confirm the boot mode persists.
Full OAuth flows: virtual-key identity and revocation window
tests/e2e/api/collections/bifrost-v1-mcp-auth.postman_collection.json
Adds end-to-end virtual-key identity OAuth tests (DCR, PKCE S256 authorize, virtual-key consent binding, token exchange, /mcp connection, refresh rotation, stolen-family revocation after replay) and revocation window tests (management API revocation, immediate refresh failure, access token still valid within window).
Session identity flow and runtime config flip
tests/e2e/api/collections/bifrost-v1-mcp-auth.postman_collection.json
Adds session-mode OAuth consent tests confirming /mcp connectivity when enforce_auth_on_inference is off and rejection after runtime enable, plus a headers-boot-only test that flips mcp_server_auth_mode to both, confirms discovery endpoints appear, and verifies header-based virtual-key /mcp remains non-401.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • akshaydeo
  • danpiths

Poem

🐇 Hoppity-hop through the OAuth maze,
Where tokens rotate and sessions ablaze,
The rabbit checks headers, then flips the mode switch,
Revocation windows — no token can snitch!
With --ignore-redirects, we leap without fear,
The MCP auth tests have finally arrived here. 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and specifically summarizes the main change: adding a comprehensive MCP auth e2e test collection covering multiple scenarios (discovery, OAuth issuance, refresh rotation, revocation window, runtime mode flip).
Description check ✅ Passed The PR description is well-structured and substantially complete. It includes a clear summary, detailed changes breakdown, type of change selection, affected areas, comprehensive testing instructions, security considerations, and properly completed checklist items.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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_mcp_oauth_server_e2e_tests

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

@greptile-apps

greptile-apps Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 5/5

Safe to merge — adds e2e test coverage only, no production code changes.

All three changed files are in the test layer: a new Postman collection, a one-line runner change (--ignore-redirects), and README updates. The collection logic is sound: partial-update semantics for PUT /api/config are confirmed by the handler code (missing fields are preserved), the revocation window correctly uses a pre/post snapshot diff to isolate the new grant, PKCE S256 computation is correct for a hex verifier, and mode-gating is consistent across all folders. The only observation is an inconsistency in WWW-Authenticate assertion coverage for two oauth-mode rejection paths.

No files require special attention.

Important Files Changed

Filename Overview
tests/e2e/api/collections/bifrost-v1-mcp-auth.postman_collection.json New 941-line Postman collection covering discovery gating, credential matrix, full OAuth flow (VK and session identity), revocation window with set-difference grant isolation, and runtime mode flip. Logic is sound; addressed the previous grant-selection ambiguity using a pre/post snapshot diff.
tests/e2e/api/runners/individual/run-newman-mcp-auth-tests.sh Adds --ignore-redirects to the Newman invocation so authorize 302 redirects are captured rather than followed, enabling Location-header extraction for flow IDs. Correct and necessary for the PKCE authorize step.
tests/e2e/api/README.md Adds the MCP Auth Tests section with per-mode assertion summaries, local run instructions, and table entry. Accurate against the actual collection and runner.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant N as Newman Runner
    participant S as Bifrost Server
    participant M as MCP Endpoint

    Note over N,M: Per mode: headers → both → oauth (fresh server each)

    N->>S: GET /.well-known/oauth-protected-resource
    S-->>N: 404 (headers) / 200 with PRM doc (both/oauth)

    N->>S: POST /oauth2/register (DCR)
    S-->>N: "201 {client_id}"

    N->>S: "GET /oauth2/authorize?response_type=code&code_challenge=S256..."
    S-->>N: "302 Location: /oauth/consent?flow=<flow_id>"

    N->>S: "PUT /api/oauth2/consent/flows/{flow_id} {mode:vk}"
    S-->>N: "200 {redirect_url?code=<auth_code>}"

    N->>S: "POST /oauth2/token grant=authorization_code"
    S-->>N: "200 {access_token, refresh_token}"

    N->>M: POST /mcp (Bearer access_token)
    M-->>N: 200 JSON-RPC initialize

    Note over N,S: Refresh rotation + stolen-token detection
    N->>S: "POST /oauth2/token grant=refresh_token"
    S-->>N: "200 {new refresh_token}"
    N->>S: POST /oauth2/token (replay old refresh_token)
    S-->>N: 400 invalid_grant (family revoked)

    Note over N,S: Revocation window
    N->>S: "DELETE /api/oauth2/sessions/{grant_id}"
    S-->>N: 204
    N->>S: "POST /oauth2/token grant=refresh_token"
    S-->>N: 400 invalid_grant
    N->>M: POST /mcp (still-valid access_token)
    M-->>N: not 401 (stateless JWT still live)
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant N as Newman Runner
    participant S as Bifrost Server
    participant M as MCP Endpoint

    Note over N,M: Per mode: headers → both → oauth (fresh server each)

    N->>S: GET /.well-known/oauth-protected-resource
    S-->>N: 404 (headers) / 200 with PRM doc (both/oauth)

    N->>S: POST /oauth2/register (DCR)
    S-->>N: "201 {client_id}"

    N->>S: "GET /oauth2/authorize?response_type=code&code_challenge=S256..."
    S-->>N: "302 Location: /oauth/consent?flow=<flow_id>"

    N->>S: "PUT /api/oauth2/consent/flows/{flow_id} {mode:vk}"
    S-->>N: "200 {redirect_url?code=<auth_code>}"

    N->>S: "POST /oauth2/token grant=authorization_code"
    S-->>N: "200 {access_token, refresh_token}"

    N->>M: POST /mcp (Bearer access_token)
    M-->>N: 200 JSON-RPC initialize

    Note over N,S: Refresh rotation + stolen-token detection
    N->>S: "POST /oauth2/token grant=refresh_token"
    S-->>N: "200 {new refresh_token}"
    N->>S: POST /oauth2/token (replay old refresh_token)
    S-->>N: 400 invalid_grant (family revoked)

    Note over N,S: Revocation window
    N->>S: "DELETE /api/oauth2/sessions/{grant_id}"
    S-->>N: 204
    N->>S: "POST /oauth2/token grant=refresh_token"
    S-->>N: 400 invalid_grant
    N->>M: POST /mcp (still-valid access_token)
    M-->>N: not 401 (stateless JWT still live)
Loading

Reviews (7): Last reviewed commit: "feat: mcp oauth server e2e tests" | Re-trigger Greptile

@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-18-feat_mcp_oauth_server_e2e_tests branch from 395dd0c to a5fa0bd Compare June 18, 2026 12:22
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-18-feat_adds_mcp_oauth_server_type_e2e_tests branch 2 times, most recently from 32e4bc0 to 0fc852e Compare June 18, 2026 12:47
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-18-feat_mcp_oauth_server_e2e_tests branch from a5fa0bd to fb2ee5f Compare June 18, 2026 12:47

@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: 1

🤖 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 `@tests/e2e/api/README.md`:
- Around line 268-269: The documentation comment for MCP auth runner options is
missing the `--mcp-port` flag from the list of supported options. Update the
comment line that documents the runner options (currently showing `--port`,
`--html`, `--json`, `--verbose`, `--bail`) to also include `--mcp-port` with an
appropriate description (e.g., default port number for MCP server). This will
allow users to easily discover and use the flag when configuring local test
runs.
🪄 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: 76273975-5e1a-4083-b462-b4bf00757edd

📥 Commits

Reviewing files that changed from the base of the PR and between 395dd0c and fb2ee5f.

📒 Files selected for processing (3)
  • tests/e2e/api/README.md
  • tests/e2e/api/collections/bifrost-v1-mcp-auth.postman_collection.json
  • tests/e2e/api/runners/individual/run-newman-mcp-auth-tests.sh

Comment thread tests/e2e/api/README.md Outdated
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-18-feat_adds_mcp_oauth_server_type_e2e_tests branch from 0fc852e to 69dff03 Compare June 22, 2026 13:15
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-18-feat_mcp_oauth_server_e2e_tests branch from fb2ee5f to 6071377 Compare June 22, 2026 13:15
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-18-feat_adds_mcp_oauth_server_type_e2e_tests branch from 69dff03 to a0d848e Compare June 22, 2026 16:58
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-18-feat_mcp_oauth_server_e2e_tests branch from 6071377 to 401b8ea Compare June 22, 2026 16:58
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-18-feat_adds_mcp_oauth_server_type_e2e_tests branch from a0d848e to e2e77f5 Compare June 23, 2026 05:30
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-18-feat_mcp_oauth_server_e2e_tests branch from 401b8ea to bbcb5a4 Compare June 23, 2026 05:30
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-18-feat_adds_mcp_oauth_server_type_e2e_tests branch from e2e77f5 to cbae6c9 Compare June 23, 2026 05:53
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-18-feat_mcp_oauth_server_e2e_tests branch from bbcb5a4 to 16504e8 Compare June 23, 2026 05:53
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