modelcontextprotocol / modelcontextprotocol/python-sdk

RequireAuthMiddleware omits RFC 6750 scope in WWW-Authenticate on 401/403

未关闭 适合新手
#3,103 2 条评论 4 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

auth bug needs confirmation P2 v1 v2
主要语言
Python
星标
24.3k
派生
4k
平均合并
1 天 1 小时
30 天内合并 PR
31

描述

Initial Checks
Description

Summary

RequireAuthMiddleware._send_auth_error builds WWW-Authenticate with error and error_description (and optional resource_metadata), but never includes the scope parameter, even when required_scopes is configured.

This breaks RFC 6750 Section 3.1 and the MCP Authorization scope-selection / step-up flow. The SDK client already expects scope via extract_scope_from_www_auth() and uses it in get_client_metadata_scopes() as the highest-priority source when handling 403 insufficient_scope.

Actual behavior

For a server configured with required_scopes=["api.read"]:

401 (no/invalid token):

WWW-Authenticate: Bearer error="invalid_token", error_description="Authentication required"

403 (token missing required scope):

WWW-Authenticate: Bearer error="insufficient_scope", error_description="Required scope: api.read"

Neither response includes scope="api.read".

Expected behavior

When required_scopes is non-empty, the challenge should include the RFC 6750 scope parameter, e.g.:

WWW-Authenticate: Bearer error="insufficient_scope", error_description="Required scope: api.read", scope="api.read"

(and similarly for 401 when scopes are configured, so the client can request the correct scopes on initial authorization).

Impact

  • MCP clients cannot reliably discover required scopes from the challenge header.
  • Step-up authorization falls back to PRM scopes_supported (or omits scope), which is lower priority per the MCP scope selection strategy and can fail when PRM does not advertise scopes.
  • The SDK client already implements the correct consumer side; only server emission is missing.

Root cause

In src/mcp/server/auth/middleware/bearer_auth.py, _send_auth_error builds:

www_auth_parts = [f'error="{error}"', f'error_description="{description}"']
if self.resource_metadata_url:
    www_auth_parts.append(f'resource_metadata="{self.resource_metadata_url}"')

It never appends scope= from self.required_scopes, which is already available on the middleware instance.

Present on both v1.x and main (verified in current source).

Suggested fix

When self.required_scopes is non-empty, append:

www_auth_parts.append(f'scope="{" ".join(self.required_scopes)}"')

Happy to open a PR against v1.x once a maintainer assigns this issue to me. Please also advise whether a follow-up for main (v2) is desired.

Example Code

Python & MCP Python SDK
Python: 3.14.6
MCP Python SDK: 1.28.1 (also reproduced against current v1.x / main source of RequireAuthMiddleware._send_auth_error)

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

从 src/mcp/server/auth/middleware/bearer_auth.py 开始,重点关注 RequireAuthMiddleware._send_auth_error 及其现有的 WWW-Authenticate 构造方式。检查周围的身份验证响应覆盖情况,然后验证配置了 required_scopes 时的 401 和 403 两种情况;完成的标准是 challenge 暴露所需的 scope,同时保留现有参数。

由索引模型根据 Issue 内容生成。

评估

技术栈
python
领域
authentication, backend, security
Issue 类型
缺陷
难度
2/5
预计耗时
1-3 小时
活跃度
冷清
描述清晰度
描述清楚
新手友好度
78/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。