test(aspnetcore): cover RequireAuthorization() on the MCP endpoint across session modes by ump45nose · Pull Request #1870 · modelcontextprotocol/csharp-sdk · GitHub
Adds end-to-end coverage for protecting the MCP endpoint itself with RequireAuthorization().
AuthorizeAttributeTests already covers tool-level [Authorize]: the request reaches the MCP handler and the tool collection is filtered per user. The endpoint-level challenge has different requirements and had no coverage — it must happen before the handler runs, it must hold for every request in an established session, and it must work in each session mode without making the OAuth protected-resource metadata document unreachable.
New file: tests/ModelContextProtocol.AspNetCore.Tests/MapMcpAuthorizationTests.cs
Initialize_WithoutCredentials_IsChallenged — the initial initialize POST is rejected with 401 in Stateful, StatefulForInitializeClients, and Stateless.
Initialize_WithCredentials_Succeeds — 200, and a session id is minted in the session-based modes but not in Stateless (which keeps the endpoint free of server state).
StatefulSession_FollowUpRequests_RequireCredentials — an authorized initialize followed by an authorized tools/list on the same session works, while the same Mcp-Session-Id sent without credentials is rejected with 401. The session id identifies a session; it must not authenticate the caller.
ResourceMetadata_RemainsReachable_WhileTheMcpEndpointIsChallenged — with MapMcp("/mcp").RequireAuthorization() and the SDK's McpAuthenticationHandler configured, GET /.well-known/oauth-protected-resource/mcp is served without credentials, and the 401 challenge advertises resource_metadata="…/.well-known/oauth-protected-resource/mcp" so a client can still discover the authorization server from the challenge alone. The endpoint is mounted at /mcp here because that is the deployment shape where the metadata document mirrors the resource path.
The authentication scheme is a test-only header-based handler, so the challenged and authorized paths are both exercised without standing up a token issuer.
No product code changes.
Verification
dotnet build tests/ModelContextProtocol.AspNetCore.Tests succeeds for net10.0, net9.0, and net8.0 with 0 warnings.
dotnet test -c Release -f net10.0 (SDK 10.0.101) on this branch:
MapMcpAuthorizationTests on its own: 8 passed, 0 failed
Only the .NET 10 runtime is installed on my machine, so the net8.0/net9.0 legs are compile-verified rather than executed here. ModelContextProtocol.Analyzers.Tests targets net9.0 only and is unaffected by this change.
Built and tested locally with -p:NuGetAudit=false: Microsoft.Build.Tasks.Git 8.0.0 raises NU1902 on this repository today, which reproduces on unmodified main and is unrelated to this change.
Related to #1785, where endpoint-level RequireAuthorization() combined with session mode was the configuration under investigation.
AI assistance disclosure: AI was used to discover this opportunity and draft the change or text. The submission was checked against the prepared artifact and recorded verification evidence.
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
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.
Summary
Adds end-to-end coverage for protecting the MCP endpoint itself with RequireAuthorization().
AuthorizeAttributeTests already covers tool-level [Authorize]: the request reaches the MCP handler and the tool collection is filtered per user. The endpoint-level challenge has different requirements and had no coverage — it must happen before the handler runs, it must hold for every request in an established session, and it must work in each session mode without making the OAuth protected-resource metadata document unreachable.
New file: tests/ModelContextProtocol.AspNetCore.Tests/MapMcpAuthorizationTests.cs
The authentication scheme is a test-only header-based handler, so the challenged and authorized paths are both exercised without standing up a token issuer.
No product code changes.
Verification
dotnet build tests/ModelContextProtocol.AspNetCore.Tests succeeds for net10.0, net9.0, and net8.0 with 0 warnings.
dotnet test -c Release -f net10.0 (SDK 10.0.101) on this branch:
Only the .NET 10 runtime is installed on my machine, so the net8.0/net9.0 legs are compile-verified rather than executed here. ModelContextProtocol.Analyzers.Tests targets net9.0 only and is unaffected by this change.
Built and tested locally with -p:NuGetAudit=false: Microsoft.Build.Tasks.Git 8.0.0 raises NU1902 on this repository today, which reproduces on unmodified main and is unrelated to this change.
Related to #1785, where endpoint-level RequireAuthorization() combined with session mode was the configuration under investigation.