20_FastMCP 2.x 中文文档之FastMCP服务端认证:令牌验证详解
一、令牌验证
通过验证外部系统颁发的承载令牌来保护您的服务器。
版本 2.11.0 新增:
令牌验证使您的 FastMCP 服务器能够验证外部系统颁发的承载令牌,而无需参与用户认证流程。您的服务器充当纯资源服务器,专注于令牌验证和授权决策,同时将身份管理委托给您基础设施中的其他系统。
注意:令牌验证在某种程度上在正式 MCP 认证流程之外运行,后者期望 OAuth 风格的发现。它最适合内部系统、微服务架构,或者当您完全控制令牌生成和分发时。
1.1 理解令牌验证
令牌验证解决了认证责任分布在多个系统中的场景。您的 MCP 服务器接收包含身份和授权信息的结构化令牌,验证其真实性,并根据其内容做出访问控制决策。
这种模式在微服务架构中自然出现,其中中央认证服务颁发多个下游服务独立验证的令牌。当将 MCP 服务器集成到已有基于令牌的认证机制的现有系统中时,它也能很好地工作。
1.2 令牌验证模型
令牌验证将您的 MCP 服务器视为 OAuth 术语中的资源服务器。关键见解是令牌验证和令牌颁发是可以由不同系统处理的独立关注点。
令牌颁发: 另一个系统(API 网关、认证服务或身份提供程序)处理用户认证并创建包含身份和权限信息的签名令牌。
令牌验证: 您的 MCP 服务器接收这些令牌,使用加密签名验证其真实性,并从中提取授权信息。
访问控制: 基于令牌内容,您的服务器确定客户端可以访问哪些资源、工具和提示。
这种分离使您的 MCP 服务器能够专注于其核心功能,同时利用现有的认证基础设施。令牌作为每个请求携带的便携式身份证明。
1.3 令牌安全考虑
基于令牌的认证依赖于加密签名来确保令牌完整性。您的 MCP 服务器使用与用于令牌创建的私钥对应的公钥来验证令牌。这种非对称方法意味着您的服务器永远不需要访问签名密钥。
令牌验证必须满足几个安全要求:签名验证确保令牌未被篡改,过期检查防止使用过时令牌,受众验证确保其他系统不会接受用于您服务器的令牌。
MCP 环境中的挑战是客户端需要在发出请求之前获取有效令牌,但 MCP 协议不提供令牌端点的内置发现机制。客户端必须通过单独的通道或预先配置来获取令牌。
二、TokenVerifier 类
FastMCP 提供 TokenVerifier 类来处理令牌验证的复杂性,同时在令牌来源和验证策略方面保持灵活性。
TokenVerifier 专门专注于令牌验证,不提供 OAuth 发现元数据。这使其成为客户端已经知道如何获取令牌的内部系统,或者信任来自已知签发者的令牌的微服务的理想选择。
该类验证令牌签名、检查过期时间戳,并从令牌声明中提取授权信息。它支持各种令牌格式和验证策略,同时为授权决策保持一致的接口。
您可以子类化 TokenVerifier 来实现特殊令牌格式或验证要求的自定义验证逻辑。基类处理常见模式,同时允许为独特用例进行扩展。
三、JWT 令牌验证
JSON Web 令牌 (JWT) 是现代应用程序中最常见的令牌格式。FastMCP 的 JWTVerifier 使用行业标准加密技术和声明验证来验证 JWT。
四、JWKS 端点集成
JWKS 端点集成为生产系统提供最灵活的方法。验证器自动从 JSON Web 密钥集端点获取公钥,实现无需服务器配置更改的自动密钥轮换。
from fastmcp import FastMCP
from fastmcp.server.auth.providers.jwt import JWTVerifier# 针对您的身份提供程序配置 JWT 验证
verifier = JWTVerifier(jwks_uri="https://auth.yourcompany.com/.well-known/jwks.json",issuer="https://auth.yourcompany.com",audience="mcp-production-api"
)mcp = FastMCP(name="Protected API", auth=verifier)
此配置创建一个验证由 auth.yourcompany.com 颁发的 JWT 的服务器。验证器定期从 JWKS 端点获取公钥,并根据这些密钥验证传入令牌。只有具有正确签发者和受众声明的令牌才会被接受。
issuer 参数确保令牌来自您信任的认证系统,而 audience 验证防止其他系统接受用于您 MCP 服务器的令牌。
五、对称密钥验证 (HMAC)
对称密钥验证使用共享密钥进行签名和验证,使其成为内部微服务和可信环境的理想选择,在这些环境中相同的密钥可以安全地分发给令牌签发者和验证者。
这种方法通常用于服务共享密钥的微服务架构中,或者当您的认证服务和 MCP 服务器都由同一组织管理时。当共享密钥得到适当管理时,HMAC 算法(HS256、HS384、HS512)提供强大的安全性。
from fastmcp import FastMCP
from fastmcp.server.auth.providers.jwt import JWTVerifier# 使用共享密钥进行对称密钥验证
verifier = JWTVerifier(public_key="your-shared-secret-key-minimum-32-chars", # 尽管名称如此,但它接受对称密钥issuer="internal-auth-service",audience="mcp-internal-api",algorithm="HS256" # 或 HS384、HS512 以获得更强的安全性
)mcp = FastMCP(name="Internal API", auth=verifier)
验证器将使用指定的 HMAC 算法验证使用相同密钥签名的令牌。这种方法为内部系统提供了几个优势:
- 简单性:无需密钥对管理或证书分发
- 性能:HMAC 操作通常比 RSA 更快
- 兼容性:与现有的微服务认证模式配合良好
注意:该参数名为 public_key 是为了向后兼容,但当使用 HMAC 算法(HS256/384/512)时,它接受对称密钥字符串。
警告:对称密钥的安全考虑:
- 使用强大的随机生成的密钥(建议至少 32 个字符)
- 切勿在日志、错误消息或版本控制中暴露密钥
- 实现安全的密钥分发和轮换机制
- 对于面向外部的 API,考虑使用非对称密钥(RSA/ECDSA)
六、静态公钥验证
当您有固定的 RSA 或 ECDSA 签名密钥且不需要自动密钥轮换时,静态公钥验证有效。这种方法主要用于开发环境或 JWKS 端点不可用的受控部署。
from fastmcp import FastMCP
from fastmcp.server.auth.providers.jwt import JWTVerifier# 使用静态公钥进行令牌验证
public_key_pem = """-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
-----END PUBLIC KEY-----"""verifier = JWTVerifier(public_key=public_key_pem,issuer="https://auth.yourcompany.com",audience="mcp-production-api"
)mcp = FastMCP(name="Protected API", auth=verifier)
此配置使用特定的 RSA 或 ECDSA 公钥验证令牌。密钥必须与您的令牌签发者使用的私钥对应。虽然不如 JWKS 端点灵活,但这种方法在开发环境或使用固定密钥测试时可能有用。
七、不透明令牌验证
许多授权服务器颁发不透明令牌而不是自包含的 JWT。不透明令牌是本身不携带任何信息的随机字符串 - 授权服务器维护其状态,验证需要查询服务器。FastMCP 通过 OAuth 2.0 令牌自省 (RFC 7662) 支持不透明令牌验证。
7.1 理解不透明令牌
不透明令牌在其验证模型上与 JWT 根本不同。JWT 携带可以在本地验证的签名声明,而不透明令牌需要网络调用到签发授权服务器进行验证。授权服务器维护令牌状态并可以立即撤销令牌,为敏感操作提供更强的安全保证。
这种方法以性能(每次验证的网络延迟)换取安全性和灵活性。授权服务器可以立即撤销不透明令牌,实现复杂的授权逻辑,并维护令牌使用的详细审计日志。许多企业 OAuth 提供程序默认使用不透明令牌以获得这些安全优势。
7.2 令牌自省协议
RFC 7662 标准化了资源服务器如何验证不透明令牌。该协议定义了一个自省端点,资源服务器使用客户端凭据进行认证,并接收令牌元数据,包括活动状态、范围、过期和主题身份。
FastMCP 通过 IntrospectionTokenVerifier 类实现此协议,根据规范处理认证、请求格式化和响应解析。
from fastmcp import FastMCP
from fastmcp.server.auth.providers.introspection import IntrospectionTokenVerifier# 使用您的 OAuth 提供程序配置自省
verifier = IntrospectionTokenVerifier(introspection_url="https://auth.yourcompany.com/oauth/introspect",client_id="mcp-resource-server",client_secret="your-client-secret",required_scopes=["api:read", "api:write"]
)mcp = FastMCP(name="Protected API", auth=verifier)
验证器使用您的客户端凭据通过 HTTP 基本认证向自省端点进行认证。当带有承载令牌的请求到达时,FastMCP 查询自省端点以确定令牌是否处于活动状态并具有足够的范围。
八、开发和测试
开发环境通常需要更简单的令牌管理,而无需完整 JWT 基础设施的复杂性。FastMCP 专门为这些场景提供了工具。
8.1 静态令牌验证
静态令牌验证通过接受具有关联声明的预定义令牌来实现快速开发。这种方法在开发和测试期间消除了对令牌生成基础设施的需求。
from fastmcp import FastMCP
from fastmcp.server.auth.providers.jwt import StaticTokenVerifier# 定义开发令牌及其关联声明
verifier = StaticTokenVerifier(tokens={"dev-alice-token": {"client_id": "alice@company.com","scopes": ["read:data", "write:data", "admin:users"]},"dev-guest-token": {"client_id": "guest-user","scopes": ["read:data"]}},required_scopes=["read:data"]
)mcp = FastMCP(name="Development Server", auth=verifier)
客户端现在可以使用 Authorization: Bearer dev-alice-token 标头进行认证。服务器将识别令牌并加载关联的声明以进行授权决策。这种方法无需外部依赖即可立即进行开发。
警告:静态令牌验证将令牌存储为纯文本,绝不应在生产环境中使用。它专门为开发和测试场景设计。
8.2 调试/自定义令牌验证
版本 2.13.1 新增:
DebugTokenVerifier 为测试和标准令牌验证不适用的特殊情况提供了最大灵活性。它将验证委托给用户提供的可调用对象,使其对于原型设计、测试场景或处理没有自省端点的不透明令牌非常有用。
from fastmcp import FastMCP
from fastmcp.server.auth.providers.debug import DebugTokenVerifier# 接受所有令牌(对快速开发有用)
verifier = DebugTokenVerifier()mcp = FastMCP(name="Development Server", auth=verifier)
默认情况下,DebugTokenVerifier 接受任何非空令牌为有效。这消除了早期开发期间的认证障碍,允许您在添加安全性之前专注于核心功能。
对于更受控的测试,提供自定义验证逻辑:
from fastmcp.server.auth.providers.debug import DebugTokenVerifier# 同步验证 - 检查令牌前缀
verifier = DebugTokenVerifier(validate=lambda token: token.startswith("dev-"),client_id="development-client",scopes=["read", "write"]
)mcp = FastMCP(name="Development Server", auth=verifier)
验证可调用对象也可以是异步的,启用数据库查找或外部服务调用:
from fastmcp.server.auth.providers.debug import DebugTokenVerifier# 异步验证 - 针对缓存检查
async def validate_token(token: str) -> bool:# 检查令牌是否存在于 Redis、数据库等中return await redis.exists(f"valid_tokens:{token}")verifier = DebugTokenVerifier(validate=validate_token,client_id="api-client",scopes=["api:access"]
)mcp = FastMCP(name="Custom API", auth=verifier)
用例:
- 测试:在集成测试期间接受任何令牌,无需设置令牌基础设施
- 原型设计:快速验证概念,无需认证复杂性
- 没有自省的不透明令牌:当您有来自不提供自省端点的 IDP 的令牌,并且您愿意接受未经验证的令牌时(验证稍后在上游服务进行)
- 自定义令牌格式:为非标准令牌格式或遗留系统实现验证
警告:DebugTokenVerifier 绕过了标准安全检查。仅在受控环境(开发、测试)中使用,或者当您完全了解安全影响时使用。对于生产,使用适当的 JWT 或基于自省的验证。
8.3 测试令牌生成
当您需要测试 JWT 验证而无需设置完整的身份基础设施时,测试令牌生成会有所帮助。FastMCP 包括用于生成测试密钥对和签名令牌的实用程序。
from fastmcp.server.auth.providers.jwt import JWTVerifier, RSAKeyPair# 为测试生成密钥对
key_pair = RSAKeyPair.generate()# 使用公钥配置您的服务器
verifier = JWTVerifier(public_key=key_pair.public_key,issuer="https://test.yourcompany.com",audience="test-mcp-server"
)# 使用私钥生成测试令牌
test_token = key_pair.create_token(subject="test-user-123",issuer="https://test.yourcompany.com", audience="test-mcp-server",scopes=["read", "write", "admin"]
)print(f"测试令牌: {test_token}")
这种模式能够在不依赖外部令牌签发者的情况下全面测试 JWT 验证逻辑。生成的令牌在密码学上是有效的,并将通过所有标准 JWT 验证检查。
九、环境配置
版本 2.12.1 新增:
FastMCP 支持令牌验证的程序化和基于环境的配置,实现在不同环境中的灵活部署。
基于环境的配置将认证设置与应用程序代码分离,遵循十二要素应用程序原则并简化部署流水线。
# 启用 JWT 验证
export FASTMCP_SERVER_AUTH=fastmcp.server.auth.providers.jwt.JWTVerifier# 对于使用 JWKS 端点的非对称验证:
export FASTMCP_SERVER_AUTH_JWT_JWKS_URI="https://auth.company.com/.well-known/jwks.json"
export FASTMCP_SERVER_AUTH_JWT_ISSUER="https://auth.company.com"
export FASTMCP_SERVER_AUTH_JWT_AUDIENCE="mcp-production-api"
export FASTMCP_SERVER_AUTH_JWT_REQUIRED_SCOPES="read:data,write:data"# 或者对于对称密钥验证 (HMAC):
export FASTMCP_SERVER_AUTH_JWT_PUBLIC_KEY="your-shared-secret-key-minimum-32-chars"
export FASTMCP_SERVER_AUTH_JWT_ALGORITHM="HS256" # 或 HS384、HS512
export FASTMCP_SERVER_AUTH_JWT_ISSUER="internal-auth-service"
export FASTMCP_SERVER_AUTH_JWT_AUDIENCE="mcp-internal-api"
配置这些环境变量后,您的 FastMCP 服务器自动启用 JWT 验证:
from fastmcp import FastMCP# 认证自动从环境配置
mcp = FastMCP(name="Production API")
这种方法使相同的代码库能够在具有不同认证要求的开发、暂存和生产环境中运行。开发可能使用静态令牌,而生产使用 JWT 验证,全部通过环境配置控制。
