Skip to content

tests: add OAuth2 issuance, JWT verification, consent, discovery, sessions, and MCP auth unit tests#4523

Open
Pratham-Mishra04 wants to merge 1 commit into
06-18-docs_adds_docs_for_mcp_oauth_serverfrom
06-18-feat_adds_unit_tests_for_mcp_oauth_server
Open

tests: add OAuth2 issuance, JWT verification, consent, discovery, sessions, and MCP auth unit tests#4523
Pratham-Mishra04 wants to merge 1 commit into
06-18-docs_adds_docs_for_mcp_oauth_serverfrom
06-18-feat_adds_unit_tests_for_mcp_oauth_server

Conversation

@Pratham-Mishra04

Copy link
Copy Markdown
Collaborator

Summary

Adds a comprehensive test suite for the OAuth2/MCP authentication layer, covering the configstore persistence layer, HTTP handler logic, JWT issuance and verification, consent flows, session management, and discovery endpoints.

Changes

  • Added configstore tests validating the OAuth2 signing key auto-generation and stability, authorize request atomic state transitions (pending → consented → code_issued), single-use code enforcement, expired code rejection, refresh token rotation and replay detection, family-wide revocation, token and client sweep/GC behavior, and the identity filter OR-group parenthesization in ListOauthUserTokens.
  • Added handler tests for getMCPServerForRequest covering the JWT path (vk/user/session modes, active/inactive VK checks, session validation matching, auth enforcement gating) and the header/anonymous path (header VK acceptance and rejection, anonymous fallback, OAuth strict mode WWW-Authenticate responses).
  • Added JWT verification tests covering all valid modes, a full matrix of rejection cases (expired, nbf in future, missing claims, issuer/audience mismatch, wrong kid, wrong signing key, non-RS256 algorithms, alg:none, malformed tokens), and infrastructure fault isolation (nil store, unavailable signing key).
  • Added consent flow tests for flowDetail (pending, missing, empty id, expired, already-consented) and flowSubmit across VK (active, inactive, unknown, empty, double-submit), session (enforced vs. not enforced), user (no resolver, resolved, no session), and VK-to-user upgrade binding (matching owner, mismatched owner, not signed in).
  • Added OAuth2 issuance handler tests for DCR registration, the authorize endpoint (happy path, loopback port flexibility, unknown client, unregistered redirect, protocol error redirects), token endpoint authorization code exchange (happy path, PKCE mismatch, single-use, expired, client_id mismatch, missing fields, unsupported grant), and refresh token rotation and replay guard.
  • Added session management handler tests for listing grants and revoking grants with identity-gated authorization (vk mode unrestricted, user mode caller-match, mismatch, unauthenticated).
  • Added discovery handler tests verifying that headers mode returns 404 on all discovery endpoints, while oauth and both modes serve PRM, AS metadata, and JWKS with correct field values.
  • Added utility tests for matchRedirectURI (exact match, loopback port flexibility, path/scheme enforcement, malformed input), oauth2IssuerURL (configured vs. request-host fallback), and oauth2ServerCfg default TTL values.
  • Introduced shared test infrastructure: mockOAuth2Store, newTestSigningKey, newTestOAuth2Config, mintTestToken, newTestMCPHandler, and real SQLite-backed store helpers for issuance tests that require actual atomic semantics.

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 ./framework/configstore/... ./transports/bifrost-http/handlers/...

All new test files are self-contained and use in-memory SQLite or mock stores; no external services are required.

Screenshots/Recordings

N/A

Breaking changes

  • No

Related issues

N/A

Security considerations

Tests explicitly cover security-critical paths: JWT algorithm confusion (alg:none, HS256, RS384), replay detection for authorization codes and refresh tokens, family-wide token revocation on replay, inactive VK rejection, identity mismatch on session revocation, and WWW-Authenticate header presence on OAuth strict mode rejections.

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

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 1e264118-4b0c-4a29-b526-109fd84e7cbf

📥 Commits

Reviewing files that changed from the base of the PR and between ce7bb1b and 0a481ed.

📒 Files selected for processing (2)
  • framework/configstore/rdb_mcp_sessions_identity_test.go
  • framework/configstore/rdb_oauth2_test.go
💤 Files with no reviewable changes (1)
  • framework/configstore/rdb_oauth2_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • framework/configstore/rdb_mcp_sessions_identity_test.go

📝 Walkthrough

Summary by CodeRabbit

  • Tests
    • Added comprehensive test coverage for OAuth2 and MCP authentication flows, including signing key generation, authorization consent, token issuance and rotation, refresh token management, session handling, JWT verification, and discovery endpoints. Test suite validates security features such as single-use code enforcement, replay detection, and token family revocation.

Walkthrough

Adds nine new test files providing comprehensive coverage for the OAuth2 and MCP authentication stack: RDB store operations (signing key generation, consent/consume lifecycle, token rotation, stale-token sweeps, session listing), HTTP handler logic (JWT extraction and verification, redirect URI matching, discovery endpoints, consent flow, DCR registration and token issuance, session management), and MCP server auth request routing across multiple authentication modes.

Changes

ConfigStore OAuth2 and MCP Sessions Tests

Layer / File(s) Summary
OAuth2 store setup and seed helpers
framework/configstore/rdb_oauth2_test.go
Defines the OAuth2 test store via AutoMigrate and adds helpers to seed authorize-request and refresh-token rows used across all OAuth2 store tests.
Signing key, consent, and authorize-request consumption tests
framework/configstore/rdb_oauth2_test.go
Tests GetOAuth2SigningKey stability, ConsentOAuth2AuthorizeRequest atomic pending→consented transition and double-consent guard, and ConsumeOAuth2AuthorizeRequest single-use and expiry rejection.
Refresh token rotation, revocation, and sweep tests
framework/configstore/rdb_oauth2_test.go
Tests RotateOAuth2RefreshToken rotation and replay guard, RevokeOAuth2RefreshTokensByFamilyID cross-family isolation, SweepOAuth2RefreshTokens stale deletion and noop for non-positive retention, and RevokeOAuth2RefreshTokensByMode mode-scoped revocation.
Client/authorize-request sweeps, session listing, and convergence
framework/configstore/rdb_oauth2_test.go
Tests SweepOrphanedOAuth2Clients grace-window behavior, SweepExpiredOAuth2AuthorizeRequests status-selective deletion, ListOAuth2Sessions VK join and revoked-session exclusion, and sweep-convergence ordering.
MCP sessions identity filter and auth-mode composition
framework/configstore/rdb_mcp_sessions_identity_test.go
Tests ListOauthUserTokens identity exact-match and correct composition of the identity OR-group with the AuthModes filter.

HTTP Handler OAuth2 Tests

Layer / File(s) Summary
mockOAuth2Store, RSA key helpers, and JWT minting
transports/bifrost-http/handlers/oauth2_jwt_test.go
Defines mockOAuth2Store implementing minimal config-store behavior, RSA keypair generation helpers, and a JWT minting helper with claim mutation support.
Bearer extraction, JWT verification, and context injection tests
transports/bifrost-http/handlers/oauth2_jwt_test.go
Table-driven tests for extractBearerJWT, verifyMCPJWT acceptance and rejection across all failure modes, config-fault error labeling, and injectJWTContext field injection per bf_mode.
Redirect URI matching, issuer URL, and server config defaults
transports/bifrost-http/handlers/oauth2_utils_test.go
Tests matchRedirectURI loopback/exact/negative cases, oauth2IssuerURL configured-vs-fallback behavior, and oauth2ServerCfg default TTL population.
OAuth2 discovery endpoint tests
transports/bifrost-http/handlers/oauth2_discovery_test.go
Tests auth-mode gating (404 for Headers, 200 for OAuth/Both), PRM and AS metadata JSON fields, and JWKS single RSA key attributes.
Consent handler: flow detail, available modes, and submit tests
transports/bifrost-http/handlers/oauth2_consent_test.go
Introduces fakeResolver and helpers; tests flowDetail status/payload, availableModes under different configs, and flowSubmit for VK, session, user, and VK→user binding upgrade modes.
Token issuance handler: SQLite store, DCR, authorize, and token exchange
transports/bifrost-http/handlers/oauth2_issuance_test.go
SQLite-backed integration tests for DCR registration, authorize redirects, authorization-code token exchange with JWT verification and PKCE/expiry/single-use rejection, and refresh token rotation with family replay revocation.
Session list and revoke handler tests
transports/bifrost-http/handlers/oauth2_sessions_test.go
Tests listSessions 200/500 paths and revokeSession across vk/user mode authorization, caller-identity matching, and 403/404/400 error mapping.
MCP server auth routing: JWT and header/anon path tests
transports/bifrost-http/handlers/mcpserver_auth_test.go
Tests getMCPServerForRequest JWT-path outcomes across auth modes, enforcement toggles, JWT-vs-header precedence, header-VK behavior, anonymous access, and WWW-Authenticate setting.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • maximhq/bifrost#3565: The main PR adds SQL-level tests for store.ListOauthUserTokens identity exact-match and its composition with AuthModes, which directly targets the per-user OAuth refactor's new mode/identity discriminator lookup semantics.
  • maximhq/bifrost#3824: Centers on ListOauthUserTokens filtering via applyMCPSessionFilters, which is the exact store method the new identity/auth-mode composition tests validate.

Suggested reviewers

  • danpiths
  • akshaydeo

Poem

🐇 Hop, hop through the OAuth maze,
Consent flows tested, tokens ablaze!
Sweep the stale ones, rotate the rest,
JWT claims put through every test.
From SQLite seeds to mock store play,
The rabbit's code is bug-free today! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding comprehensive unit tests for OAuth2/MCP authentication across multiple layers (issuance, JWT, consent, discovery, sessions, MCP auth).
Description check ✅ Passed The description covers all required template sections with substantial detail: Summary explains purpose, Changes lists all test additions and infrastructure, Type clearly marks as Chore/CI, Affected areas selected, How to test provided with commands, Breaking changes marked No, and Checklist items appropriately checked.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 06-18-feat_adds_unit_tests_for_mcp_oauth_server

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


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

This PR adds only test files with no changes to production code and is safe to merge.

All nine files are new test files. No production logic is modified. The tests use real SQLite for paths that need atomic store semantics and mock stores for handler-level logic. Mock fidelity gaps exist but do not cause false positives or miss security regressions in the current test run.

transports/bifrost-http/handlers/oauth2_jwt_test.go (nil-interface risk in mockOAuth2Store), transports/bifrost-http/handlers/oauth2_sessions_test.go (RevokeOAuth2Session fidelity gap), transports/bifrost-http/handlers/oauth2_issuance_test.go (missing unknown-token-hash sub-test)

Important Files Changed

Filename Overview
framework/configstore/rdb_oauth2_test.go Comprehensive SQLite-backed store tests covering signing key stability, atomic state transitions, single-use code enforcement, refresh token rotation/replay/family-revocation, and sweep/GC behavior.
framework/configstore/rdb_mcp_sessions_identity_test.go Pins the identity OR-group parenthesization in ListOauthUserTokens, verifying exact-match per auth mode and that the identity filter cannot leak rows across auth modes.
transports/bifrost-http/handlers/oauth2_jwt_test.go Introduces shared test infrastructure and a full JWT rejection matrix. The mockOAuth2Store embeds a nil ConfigStore interface that will panic on any unimplemented method call.
transports/bifrost-http/handlers/mcpserver_auth_test.go Tests getMCPServerForRequest across all JWT and header/anonymous paths; security-critical gating coverage is thorough.
transports/bifrost-http/handlers/oauth2_consent_test.go Tests flowDetail and flowSubmit across all identity modes including VK-to-user upgrade binding and double-submit protection.
transports/bifrost-http/handlers/oauth2_issuance_test.go Real SQLite store tests for DCR, authorize, token exchange, and refresh rotation/replay. Missing a sub-test for a completely unknown refresh token hash.
transports/bifrost-http/handlers/oauth2_sessions_test.go Tests listSessions and identity-gated revokeSession. The mock's RevokeOAuth2Session does not remove from sessionByID, so a double-revoke would incorrectly return 204 twice.
transports/bifrost-http/handlers/oauth2_discovery_test.go Verifies headers mode returns 404 on all discovery endpoints while oauth/both modes serve PRM, AS metadata, and JWKS with correct field values.
transports/bifrost-http/handlers/oauth2_utils_test.go Table-driven tests for matchRedirectURI, oauth2IssuerURL, and oauth2ServerCfg default TTL values. Compact and correct.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Client
    participant IssuanceHandler
    participant ConsentHandler
    participant Store
    participant JWTVerifier

    Client->>IssuanceHandler: GET /oauth2/authorize
    IssuanceHandler->>Store: CreateOAuth2AuthorizeRequest (pending)
    IssuanceHandler-->>Client: 302 to consent page

    Client->>ConsentHandler: PUT consent flow (mode, value)
    ConsentHandler->>Store: ConsentOAuth2AuthorizeRequest (pending to consented)
    ConsentHandler-->>Client: 200 redirect_url with code

    Client->>IssuanceHandler: POST /oauth2/token (code, verifier)
    IssuanceHandler->>Store: ConsumeOAuth2AuthorizeRequest (consented to code_issued)
    IssuanceHandler->>Store: GetOAuth2SigningKey
    IssuanceHandler-->>Client: 200 access_token + refresh_token

    Client->>JWTVerifier: Bearer access_token
    JWTVerifier->>Store: GetOAuth2SigningKey
    JWTVerifier-->>Client: verified claims

    Client->>IssuanceHandler: POST /oauth2/token (refresh_token)
    IssuanceHandler->>Store: GetOAuth2RefreshTokenByHash
    alt active token
        IssuanceHandler->>Store: RotateOAuth2RefreshToken
        IssuanceHandler-->>Client: 200 new token pair
    else revoked token replay
        IssuanceHandler->>Store: RevokeOAuth2RefreshTokensByFamilyID
        IssuanceHandler-->>Client: 400 invalid_grant
    end
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 Client
    participant IssuanceHandler
    participant ConsentHandler
    participant Store
    participant JWTVerifier

    Client->>IssuanceHandler: GET /oauth2/authorize
    IssuanceHandler->>Store: CreateOAuth2AuthorizeRequest (pending)
    IssuanceHandler-->>Client: 302 to consent page

    Client->>ConsentHandler: PUT consent flow (mode, value)
    ConsentHandler->>Store: ConsentOAuth2AuthorizeRequest (pending to consented)
    ConsentHandler-->>Client: 200 redirect_url with code

    Client->>IssuanceHandler: POST /oauth2/token (code, verifier)
    IssuanceHandler->>Store: ConsumeOAuth2AuthorizeRequest (consented to code_issued)
    IssuanceHandler->>Store: GetOAuth2SigningKey
    IssuanceHandler-->>Client: 200 access_token + refresh_token

    Client->>JWTVerifier: Bearer access_token
    JWTVerifier->>Store: GetOAuth2SigningKey
    JWTVerifier-->>Client: verified claims

    Client->>IssuanceHandler: POST /oauth2/token (refresh_token)
    IssuanceHandler->>Store: GetOAuth2RefreshTokenByHash
    alt active token
        IssuanceHandler->>Store: RotateOAuth2RefreshToken
        IssuanceHandler-->>Client: 200 new token pair
    else revoked token replay
        IssuanceHandler->>Store: RevokeOAuth2RefreshTokensByFamilyID
        IssuanceHandler-->>Client: 400 invalid_grant
    end
Loading

Reviews (5): Last reviewed commit: "feat: adds unit tests for mcp oauth serv..." | Re-trigger Greptile

@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-18-feat_adds_unit_tests_for_mcp_oauth_server branch from 5e5e90a to 5ee117b Compare June 18, 2026 12:22
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-18-docs_adds_docs_for_mcp_oauth_server branch from 91623fa to 045411d Compare June 18, 2026 12:22
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-18-feat_adds_unit_tests_for_mcp_oauth_server branch from 5ee117b to ce7bb1b Compare June 18, 2026 12:47
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-18-docs_adds_docs_for_mcp_oauth_server branch from 045411d to 7cae97e Compare June 18, 2026 12:47
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-18-feat_adds_unit_tests_for_mcp_oauth_server branch from ce7bb1b to e30b088 Compare June 22, 2026 13:15
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-18-docs_adds_docs_for_mcp_oauth_server branch from 7cae97e to 736beb4 Compare June 22, 2026 13:15
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-18-docs_adds_docs_for_mcp_oauth_server branch from 736beb4 to f48f3dd Compare June 22, 2026 16:58
@Pratham-Mishra04 Pratham-Mishra04 force-pushed the 06-18-feat_adds_unit_tests_for_mcp_oauth_server branch from e30b088 to 0a481ed Compare June 22, 2026 16:58
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