Fix: 401 Unauthorized on all [Authorize]-protected MCP tools due to premature authentication check#3
Open
alealoisi-nts wants to merge 3 commits intokaladinstorm84:mainfrom
Open
Fix: 401 Unauthorized on all [Authorize]-protected MCP tools due to premature authentication check#3alealoisi-nts wants to merge 3 commits intokaladinstorm84:mainfrom
alealoisi-nts wants to merge 3 commits intokaladinstorm84:mainfrom
Conversation
…P tools **Why:** The `Authorization` header is already correctly forwarded from the MCP request to the synthetic `HttpContext` by `SyntheticHttpContextFactory`. However, the early auth check evaluates `context.User` before `invoker.InvokeAsync()` has run — meaning authentication has never been executed yet and `User` is always empty. The check therefore always returns 401 for any protected endpoint, regardless of whether valid credentials were provided. Removing it lets the full ASP.NET Core filter pipeline run normally, which correctly authenticates the user from the forwarded header.
Owner
|
Could you please add this change to zeroMcp/zeromcp.net as this repo has been migrated and is in the process of being wound down. I would migrate the changes over myself, but would like you to maintain the credit |
kaladinstorm84
approved these changes
Mar 3, 2026
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.
Problem
When an MCP client calls a tool mapped to a controller action protected by
[Authorize], the dispatcher always returns401 Unauthorized— even whenvalid credentials are present in the
Authorizationheader.Root Cause
McpToolDispatcher.DispatchAsync()contained an early authentication guard:This check evaluates
context.Useron the freshly built syntheticHttpContextbefore
invoker.InvokeAsync()is called. Since authentication runs as partof the ASP.NET Core filter pipeline (inside
InvokeAsync), theUserprincipalis always empty at this point — causing every protected tool to be rejected
regardless of the credentials provided.
The
Authorizationheader forwarding inSyntheticHttpContextFactorywasalready working correctly — the header is present on the synthetic request,
but the early check prevented the pipeline from ever reading it.
Fix
RequiresAuthentication/IsAuthenticatedguard block fromDispatchAsyncand their two helper methods.pipeline, which correctly reads the forwarded
Authorizationheader andauthenticates the user before the action executes.
Testing
Verified with an ASP.NET Core API using
[Authorize(AuthenticationSchemes = "Basic")]at controller level. After this fix, MCP tool calls with a valid
Authorization: Basicheader are correctly authenticated and return
200 OK.