test(gateway): end-to-end coverage for both auth-enabled and no-auth flows - #188
Merged
Conversation
The earlier no-auth tests stubbed the `/mcp` handler and only checked two discovery endpoints — so they couldn't catch the real failure an editor hit: with auth disabled but discovery still advertising OAuth (the pre-#187 state), VS Code probed `/.well-known/oauth-protected-resource/mcp`, got 200, entered an OAuth flow, and stalled at `initialize`. - auth_disable: assert the RFC 9728 `/.well-known/oauth-protected-resource/mcp` sub-path (the one editors probe first) 404s when auth is disabled and is served when required, alongside the other two endpoints. - gateway_notifications: add `authless_anonymous_client_completes_real_initialize` — boots the real gateway with the REAL `mcp_oauth_middleware` + auth disabled and drives it with a real rmcp client that sends no token, proving the anonymous handshake completes end to end (initialize + list_tools) rather than hanging. Claude-Session: https://claude.ai/code/session_01Baan9JmzR43uxxRUh7CAMF Signed-off-by: Mohammod Al Amin Ashik <maa.ashik00@gmail.com>
Adds a real end-to-end test of the AUTH-REQUIRED path so we can guarantee the "disable auth" feature never silently regresses real OAuth. It drives the actual production handlers over HTTP against a gateway with inbound auth required + a JWT secret configured: DCR register → authorize (consent page, request_id) → consent approve (redirect with code) → token exchange (PKCE S256) → authenticated /mcp handshake returns 200; the same handshake with no token returns 401. To mount the flow in a self-contained harness, expose the OAuth handlers (oauth_register/authorize/token/consent_approve) from the server module, the same way the discovery handlers were already exposed for tests. Together with the disabled-side coverage (anonymous real handshake + list_tools, discovery 404 incl. the RFC 9728 /mcp sub-path), both auth modes are now proven end to end. Claude-Session: https://claude.ai/code/session_01Baan9JmzR43uxxRUh7CAMF Signed-off-by: Mohammod Al Amin Ashik <maa.ashik00@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Comprehensive E2E coverage for inbound auth, prompted by real reports while toggling auth (no-auth "stuck at initialize", and "is the enabled flow still intact?"). No production behavior change — these are tests plus exposing existing handlers for tests.
Auth DISABLED (no-auth)
authless_anonymous_client_completes_real_initialize— boots the real gateway with the realmcp_oauth_middleware+ auth disabled, drives it with a real rmcp client that sends no token, and proves the anonymous handshake completes end to end (initialize+list_tools).404when disabled /200when required — including the RFC 9728/.well-known/oauth-protected-resource/mcpsub-path that editors (VS Code) probe first (its stale200was what pushed clients into an OAuth flow against an authless gateway).Auth ENABLED (full OAuth)
auth_enabled_full_oauth_flow_then_authenticated_mcp— drives the real production handlers over HTTP against a gateway with auth required + JWT secret:DCR register → authorize (consent page) → consent approve (redirect + code) → token exchange (PKCE S256) → authenticated
/mcphandshake200, and a tokenless/mcp→401.This guarantees the "disable auth" feature can't silently regress real OAuth.
To mount the flow self-contained, the OAuth handlers (
oauth_register/authorize/token/consent_approve) are nowpub use-exported from the server module — the same pattern already used for the discovery handlers.All 24 streamable_http tests pass locally.
https://claude.ai/code/session_01Baan9JmzR43uxxRUh7CAMF