一、AWS Cognito OAuth 🤝 FastMCP

使用 AWS Cognito 用户池保护您的 FastMCP 服务器

新版本:2.12.4 功能

本指南展示如何使用 AWS Cognito 用户池 保护您的 FastMCP 服务器。由于 AWS Cognito 不支持动态客户端注册,此集成采用 OAuth 代理 模式,将 AWS Cognito 的传统 OAuth 与 MCP 的认证要求相连接。同时包含强大的 JWT 令牌验证,确保企业级认证安全性。

二、配置

2.1 前提条件

开始之前,您需要:

  • 拥有 AWS 账户,并具备创建 AWS Cognito 用户池的权限

  • 基本熟悉 AWS Cognito 概念(用户池、应用客户端)

  • 您的 FastMCP 服务器 URL(开发环境可使用 localhost,例如 http://localhost:8000)

2.2 步骤 1:创建 AWS Cognito 用户池和应用客户端

设置 AWS Cognito 用户池和应用客户端,获取认证所需凭证:

进入 AWS Cognito 控制台

  • 访问 AWS Cognito 控制台,确保处于目标 AWS 区域。

  • 从侧边导航选择 “User pools”(如未看到请点击左上角菜单图标),然后点击 “Create user pool” 创建新用户池。

定义应用类型

AWS Cognito 现在提供简化的设置体验:

  • 应用类型: 选择 “Traditional web application”(这是 FastMCP 服务器端认证的正确选择)

  • 应用名称: 输入描述性名称(例如 FastMCP Server)

传统 Web 应用类型自动配置:

  • 带客户端密钥的服务器端认证

  • 授权码授权流程

  • 机密客户端的适当安全设置

注意:选择 “Traditional web application” 而非 SPA、移动应用或机器对机器选项,确保为 FastMCP 提供正确的 OAuth 2.0 配置。

配置选项

AWS 将引导您完成配置选项:

  • 登录标识符: 选择用户登录方式(邮箱、用户名或电话)

  • 必需属性: 选择所需的额外用户信息

  • 返回 URL: 添加回调 URL(例如开发环境使用 http://localhost:8000/auth/callback)

提示:简化界面会根据您的应用类型选择自动处理大多数 OAuth 安全设置。

审核并创建

审核配置并点击 “Create user pool”。

创建后,您将看到用户池详情。保存这些重要值:

  • 用户池 ID(格式:eu-central-1_XXXXXXXXX)

  • 客户端 ID(在 → “Applications” → “App clients” → <您的应用名称> → “App client information” 中查找)

  • 客户端密钥(在 → “Applications” → “App clients” → <您的应用名称> → “App client information” 中查找)

提示:用户池 ID 和应用客户端凭证是 FastMCP 配置所需的全部信息。

配置 OAuth 设置

在应用客户端设置的 “Login pages” 下,您可以复查和调整 OAuth 配置:

  • Allowed callback URLs: 添加服务器 URL + /auth/callback(例如 http://localhost:8000/auth/callback)

  • Allowed sign-out URLs: 可选,用于注销功能

  • OAuth 2.0 grant types: 确保选择 “Authorization code grant”

  • OpenID Connect scopes: 选择应用所需的作用域(例如 openid、email、profile)

提示:本地开发可使用 http://localhost URL,生产环境必须使用 HTTPS。

配置资源服务器

AWS Cognito 需要资源服务器条目来支持带受保护资源的 OAuth。若无此配置,令牌交换将失败并返回 invalid_grant 错误。

在侧边导航中进入 “Branding” → “Domain”,然后:

  • 点击 “Create resource server

  • Resource server name: 输入描述性名称(例如 My MCP Server)

  • Resource server identifier: 准确输入 MCP 端点 URL(如开发环境使用 http://localhost:8000/mcp,生产环境使用 https://your-server.com/mcp)

  • 点击 “Create resource server

警告:资源服务器标识符必须完全匹配 base_url + mcp_path。对于默认配置 base_url=“http://localhost:8000” 和 path=“/mcp”,请使用 http://localhost:8000/mcp。

保存凭证

设置完成后,您将获得:

  • 用户池 ID: 格式如 eu-central-1_XXXXXXXXX

  • 客户端 ID: 应用的客户端标识符

  • 客户端密钥: 生成的客户端密钥(请安全保存)

  • AWS 区域: AWS Cognito 用户池所在区域

提示:请安全存储这些凭证,切勿提交到版本控制系统。生产环境请使用环境变量或 AWS Secrets Manager。

2.3 步骤 2:FastMCP 配置

使用 AWSCognitoProvider 创建 FastMCP 服务器,该提供者自动处理 AWS Cognito 的 JWT 令牌和用户声明:

from fastmcp import FastMCP
from fastmcp.server.auth.providers.aws import AWSCognitoProvider
from fastmcp.server.dependencies import get_access_token

# AWSCognitoProvider 处理 JWT 验证和用户声明
auth_provider = AWSCognitoProvider(
    user_pool_id="eu-central-1_XXXXXXXXX",   # 您的 AWS Cognito 用户池 ID
    aws_region="eu-central-1",               # AWS 区域(默认为 eu-central-1)
    client_id="your-app-client-id",          # 您的应用客户端 ID
    client_secret="your-app-client-secret",  # 您的应用客户端密钥
    base_url="http://localhost:8000",        # 必须与回调 URL 匹配
    # redirect_path="/auth/callback"         # 默认值,可按需自定义
)

mcp = FastMCP(name="AWS Cognito Secured App", auth=auth_provider)

# 添加受保护工具以测试认证
@mcp.tool
async def get_access_token_claims() -> dict:
    """获取认证用户的访问令牌声明。"""
    token = get_access_token()
    return {
        "sub": token.claims.get("sub"),
        "username": token.claims.get("username"),
        "cognito:groups": token.claims.get("cognito:groups", []),
    }

三、测试

3.1 运行服务器

启动使用 HTTP 传输的 FastMCP 服务器以启用 OAuth 流程:

fastmcp run server.py --transport http --port 8000

您的服务器现已运行并受到 AWS Cognito OAuth 认证保护。

3.2 客户端测试

创建测试客户端,与受 AWS Cognito 保护的服务器进行认证:

from fastmcp import Client
import asyncio

async def main():
    # 客户端将自动处理 AWS Cognito OAuth
    async with Client("http://localhost:8000/mcp", auth="oauth") as client:
        # 首次连接将在浏览器中打开 AWS Cognito 登录页面
        print("✓ 已通过 AWS Cognito 认证!")

        # 测试受保护工具
        print("调用受保护工具:get_access_token_claims")
        result = await client.call_tool("get_access_token_claims")
        user_data = result.data
        print("可用的访问令牌声明:")
        print(f"- sub: {user_data.get('sub', 'N/A')}")
        print(f"- username: {user_data.get('username', 'N/A')}")
        print(f"- cognito:groups: {user_data.get('cognito:groups', [])}")

if __name__ == "__main__":
    asyncio.run(main())

首次运行客户端时:

  • 浏览器将打开 AWS Cognito 托管 UI 登录页面

  • 登录(或注册)后,您将被重定向回 MCP 服务器

  • 客户端接收 JWT 令牌并可进行认证请求

提示:客户端会在本地缓存令牌,因此除非令牌过期或您明确清除缓存,后续运行无需重新认证。

四、生产环境配置

新版本:2.13.0 功能

对于需要跨服务器重启持久化令牌管理的生产环境部署,请配置 jwt_signing_key 和 client_storage:

import os
from fastmcp import FastMCP
from fastmcp.server.auth.providers.aws import AWSCognitoProvider
from key_value.aio.stores.redis import RedisStore
from key_value.aio.wrappers.encryption import FernetEncryptionWrapper
from cryptography.fernet import Fernet

# 使用加密持久化令牌存储的生产环境设置
auth_provider = AWSCognitoProvider(
    user_pool_id="eu-central-1_XXXXXXXXX",
    aws_region="eu-central-1",
    client_id="your-app-client-id",
    client_secret="your-app-client-secret",
    base_url="https://your-production-domain.com",

    # 生产环境令牌管理
    jwt_signing_key=os.environ["JWT_SIGNING_KEY"],
    client_storage=FernetEncryptionWrapper(
        key_value=RedisStore(
            host=os.environ["REDIS_HOST"],
            port=int(os.environ["REDIS_PORT"])
        ),
        fernet=Fernet(os.environ["STORAGE_ENCRYPTION_KEY"])
    )
)

mcp = FastMCP(name="Production AWS Cognito App", auth=auth_provider)

注意:参数 jwt_signing_key 和 client_storage 共同确保令牌和客户端注册在服务器重启后得以保留。使用 FernetEncryptionWrapper 包装存储以加密静态的敏感 OAuth 令牌 - 若无此包装,令牌将以明文存储。将密钥存储在环境变量中,对于分布式部署使用如 Redis 的持久化存储后端。

有关这些参数的完整详情,请参阅 OAuth 代理文档

五、环境变量

对于生产环境部署,请使用环境变量而非硬编码凭证。

5.1 提供者选择

设置此环境变量可自动使用 AWS Cognito 提供者,无需在代码中显式实例化。

FASTMCP_SERVER_AUTH:设置为 fastmcp.server.auth.providers.aws.AWSCognitoProvider 以使用 AWS Cognito 认证

5.2 AWS Cognito 特定配置

这些环境变量为 AWS Cognito 提供者提供默认值,无论是手动实例化还是通过 FASTMCP_SERVER_AUTH 配置。

FASTMCP_SERVER_AUTH_AWS_COGNITO_USER_POOL_ID:您的 AWS Cognito 用户池 ID(例如 eu-central-1_XXXXXXXXX)
FASTMCP_SERVER_AUTH_AWS_COGNITO_AWS_REGION:您的 AWS Cognito 用户池所在区域(默认为 eu-central-1)
FASTMCP_SERVER_AUTH_AWS_COGNITO_CLIENT_ID:您的 AWS Cognito 应用客户端 ID
FASTMCP_SERVER_AUTH_AWS_COGNITO_CLIENT_SECRET:您的 AWS Cognito 应用客户端密钥
FASTMCP_SERVER_AUTH_AWS_COGNITO_BASE_URL:OAuth 端点可访问的公共 URL(包含任何挂载路径,默认为 http://localhost:8000)
FASTMCP_SERVER_AUTH_AWS_COGNITO_ISSUER_URL:OAuth 元数据的签发者 URL(默认为 BASE_URL)。当在路径前缀下挂载时,设置为根级 URL 以避免 404 日志。详见 [HTTP 部署指南](/deployment/http#mounting-authenticated-servers)
FASTMCP_SERVER_AUTH_AWS_COGNITO_REDIRECT_PATH:在 AWS Cognito 应用客户端中配置的重定向路径之一(默认为 /auth/callback)
FASTMCP_SERVER_AUTH_AWS_COGNITO_REQUIRED_SCOPES:必需的 OAuth 作用域列表,支持逗号、空格或 JSON 分隔(例如 openid email 或 ["openid","email","profile"]

示例 .env 文件:

# 使用 AWS Cognito 提供者
FASTMCP_SERVER_AUTH=fastmcp.server.auth.providers.aws.AWSCognitoProvider

# AWS Cognito 凭证
FASTMCP_SERVER_AUTH_AWS_COGNITO_USER_POOL_ID=eu-central-1_XXXXXXXXX
FASTMCP_SERVER_AUTH_AWS_COGNITO_AWS_REGION=eu-central-1
FASTMCP_SERVER_AUTH_AWS_COGNITO_CLIENT_ID=your-app-client-id
FASTMCP_SERVER_AUTH_AWS_COGNITO_CLIENT_SECRET=your-app-client-secret
FASTMCP_SERVER_AUTH_AWS_COGNITO_BASE_URL=https://your-server.com
FASTMCP_SERVER_AUTH_AWS_COGNITO_REQUIRED_SCOPES=openid,email,profile

设置环境变量后,您的服务器代码简化为:

from fastmcp import FastMCP
from fastmcp.server.dependencies import get_access_token

# 认证自动从环境变量配置
mcp = FastMCP(name="AWS Cognito Secured App")

@mcp.tool
async def get_access_token_claims() -> dict:
    """获取认证用户的访问令牌声明。"""
    token = get_access_token()
    return {
        "sub": token.claims.get("sub"),
        "username": token.claims.get("username"),
        "cognito:groups": token.claims.get("cognito:groups", []),
    }

六、功能特性

6.1 JWT 令牌验证

AWS Cognito 提供者包含强大的 JWT 令牌验证:

  • 签名验证:根据 AWS Cognito 公钥(JWKS)验证令牌

  • 过期检查:自动拒绝过期令牌

  • 签发者验证:确保令牌来自特定 AWS Cognito 用户池

  • 作用域强制:验证必需的 OAuth 作用域是否存在

6.2 用户声明和组

从 AWS Cognito JWT 令牌访问丰富的用户信息:

from fastmcp.server.dependencies import get_access_token

@mcp.tool
async def admin_only_tool() -> str:
    """仅对管理员用户可用的工具。"""
    token = get_access_token()
    user_groups = token.claims.get("cognito:groups", [])

    if "admin" not in user_groups:
        raise ValueError("此工具需要管理员权限")

    return "管理员访问已授权!"

6.3 企业集成

完美适合企业环境,具备:

  • 单点登录(SSO): 与企业身份提供商集成

  • 多因素认证(MFA): 利用 AWS Cognito 内置 MFA

  • 用户组: 通过 AWS Cognito 组实现基于角色的访问控制

  • 自定义属性: 访问 AWS Cognito 用户池中定义的自定义用户属性

  • 合规性: 满足企业安全和合规要求

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐