资讯动态

使用 Oracle OCI IAM(Identity Domain)OAuth 保护 FastMCP 服务器:完整接入指南

发布时间:2026/9/11 6:09:12 来源:尧图企业网站定制
使用 Oracle OCI IAMIdentity DomainOAuth 保护 FastMCP 服务器完整接入指南【免费下载链接】fastmcp The fast, Pythonic way to build MCP servers and clients.项目地址: https://gitcode.com/GitHub_Trending/fa/fastmcp本文以 examples/auth/oci_oauth 示例为基础讲解如何将 FastMCP 服务器接入 Oracle Cloud InfrastructureOCIIAM Identity Domain 的 OAuth 授权体系涵盖 OCI 控制台应用注册、环境变量配置、服务端与客户端代码编写、运行验证以及调用 OCI 控制面 API 所需的令牌交换Token Exchange与生产环境持久化配置。读完本文你将能够把一个 FastMCP 服务器从裸奔状态升级为受 OCI IAM 身份认证保护的安全服务并打通登录用户身份 → OCI 控制面 API的身份传播链路。集成原理OIDC Proxy 模式OCI IAMIdentity Domain不提供动态客户端注册Dynamic Client Registration无法直接满足 MCP 协议对 OAuth 动态发现的全部要求。FastMCP 因此采用OIDC Proxy 模式完成桥接FastMCP 自身充当 OAuth 授权服务器代理上游对接 OCI IAM Identity Domain 的标准 OIDC 发现端点下游对 MCP 客户端暴露标准 OAuth 端点。从源码看OCIProvider直接继承自 OIDCProxy 基类class OCIProvider(OIDCProxy): An OCI IAM Domain provider implementation for FastMCP.该基类位于 fastmcp_slim/fastmcp/server/auth/oidc_proxy.py负责 OIDC discovery默认超时 10 秒见DEFAULT_OIDC_DISCOVERY_TIMEOUT_SECONDS、JWKS 校验、授权码流程、令牌签发与刷新等核心逻辑。你只需要向OCIProvider提供发现 URLconfig_url、client ID、client secret 和 base_url四个参数即可完成整套 OCI 集成。前置条件开始之前你需要准备一个 OCI 云账号并有权限在某个 Identity Domain 中创建 Integrated Application集成应用。你的 FastMCP 服务器的公网可达 URL。开发环境通常为http://localhost:8000生产环境为https://mcp.yourdomain.com之类的 HTTPS 域名。本地已安装 FastMCP 包本文示例位于仓库 examples/auth/oci_oauth 目录可直接运行。第一步在 OCI 控制台注册 OAuth 客户端OCI 控制台的操作步骤较多请按以下流程逐步完成。更详细的分步截图教程可参考官方集成文档 docs/integrations/oci.mdx。1.1 在 Domain 设置中启用客户端访问登录 OCI 控制台商业云地址为 https://cloud.oracle.com。从Identity Security身份与安全菜单打开Domains域页面。在域列表中选择用于 MCP 认证的域打开Settings设置标签页。点击Edit Domain Settings编辑域设置按钮勾选Configure client access配置客户端访问复选框并保存。这一步骤确保 MCP 服务器能够访问 OCI IAM 域的 JWKSJSON Web Key Set签名证书端点是后续 JWT 校验的前提。1.2 创建 Confidential Application在域的详情页选择Integrated applications集成应用页面会列出该域下所有应用。点击Add application添加应用。在弹出的窗口中选择Confidential Application机密应用点击Launch workflow启动工作流。在Add application details应用详情页填写名称和描述创建应用。应用创建完成后进入OAuth configurationOAuth 配置标签页点击Edit OAuth configuration编辑 OAuth 配置按钮。选择Configure this application as a client now立即将此应用配置为客户端单选按钮。授权类型Grant type必须勾选Authorization code授权码。如果你计划使用同一个 OAuth 客户端应用进行令牌交换Token Exchange用于调用 OCI 控制面 API请同时勾选Client credentials客户端凭证。本示例即使用同一个客户端。重定向 URLRedirect URL在大多数情况下填写你的 MCP 服务器 URL 后接/auth/callback例如http://localhost:8000/auth/callback。点击Submit提交 OAuth 配置更新。激活应用确保将客户端应用Activate激活否则授权请求会被拒绝。记下应用的Client ID和Client Secret后续配置OCIProvider时需要用到。无需为 OAuth 客户端做任何额外的 PKCE 特殊配置FastMCP 客户端会自动处理 PKCE 挑战。第二步设置环境变量示例服务端 server.py 通过三个环境变量读取 OCI 凭证# Required FASTMCP_SERVER_AUTH_IDCS_CLIENT_IDyour-application-client-id FASTMCP_SERVER_AUTH_IDCS_CLIENT_SECRETyour-client-secret-value FASTMCP_SERVER_AUTH_IDCS_DOMAINyour-iam-domain-url # IDCS domain URL for example idcs-abscasdwdac3432rdwsda.identity.oraclecloud.com环境变量是否必需说明FASTMCP_SERVER_AUTH_IDCS_CLIENT_ID是OCI IAM 集成应用的客户端 IDFASTMCP_SERVER_AUTH_IDCS_CLIENT_SECRET是集成应用的客户端密钥FASTMCP_SERVER_AUTH_IDCS_DOMAIN是IDCS 域 URL形如idcs-abscasdwdac3432rdwsda.identity.oraclecloud.com不含https://前缀示例代码会自行拼接第三步编写受保护的服务端examples/auth/oci_oauth/server.py 展示了最精简的接入方式import os from fastmcp import FastMCP from fastmcp.server.auth.providers.oci import OCIProvider auth OCIProvider( client_idos.getenv(FASTMCP_SERVER_AUTH_IDCS_CLIENT_ID) or , client_secretos.getenv(FASTMCP_SERVER_AUTH_IDCS_CLIENT_SECRET) or , config_urlfhttps://{os.getenv(FASTMCP_SERVER_AUTH_IDCS_DOMAIN)}/.well-known/openid-configuration or , base_urlhttp://localhost:8000, # redirect_path/auth/callback, # Default path - change if using a different callback URL ) mcp FastMCP(OCI OAuth Example Server, authauth) mcp.tool def echo(message: str) - str: Echo the provided message. return message if __name__ __main__: mcp.run(transporthttp, port8000, hostlocalhost)关键点解读config_url指向 OCI IAM 域的 OIDC discovery 端点/.well-known/openid-configurationFastMCP 在构造OCIProvider时会主动拉取该配置单元测试 tests/server/auth/providers/test_oci.py 通过 mock 验证了 discovery 请求确实会发起一次。redirect_path默认即为/auth/callback与 OCI 控制台填写的重定向 URL 保持一致若你在控制台使用了不同的回调路径需在此同步修改。将auth对象传入FastMCP(OCI OAuth Example Server, authauth)后服务器上注册的每个工具如这里的echo都会要求有效令牌才能调用。第四步编写客户端并运行examples/auth/oci_oauth/client.py 演示了如何连接受保护的服务端import asyncio from fastmcp.client import Client SERVER_URL http://localhost:8000/mcp async def main(): try: async with Client(SERVER_URL, authoauth) as client: assert await client.ping() print(✅ Successfully authenticated!) tools await client.list_tools() print(f Available tools ({len(tools)}):) for tool in tools: print(f - {tool.name}: {tool.description}) except Exception as e: print(f❌ Authentication failed: {e}) raise if __name__ __main__: asyncio.run(main())运行步骤在 examples/auth/oci_oauth 目录下先确保环境变量已导出# 启动服务端 python server.py # 另开终端运行客户端 python client.py首次运行客户端的完整交互流程客户端自动探测服务器 OAuth 元数据检测到需要授权自动在本地浏览器打开 OCI IAM 域的登录页面你用 OCI 账号登录并同意授权consent授权成功后浏览器被重定向回/auth/callback客户端完成授权码换取令牌客户端持有令牌ping()与list_tools()等请求即可通过认证控制台输出✅ Successfully authenticated!及工具列表。FastMCP 客户端会在本地缓存令牌后续再次运行无需重复登录除非令牌过期或你显式清除缓存。深入源码OCIProvider 核心参数除示例中使用的四个参数外OCIProvider 实现 还暴露了丰富的可调参数理解它们有助于你应对生产场景参数默认值说明config_url必填OCI IAM 域的 OIDC Discovery URLclient_id/client_secret必填OCI 集成应用的客户端 ID 与密钥base_url必填OIDC 端点对外可达的公网基础 URL含挂载路径timeout_seconds10OIDC discovery 请求超时秒避免缓慢或不可达的 issuer 阻塞服务器启动resource_base_urlbase_url受保护资源元数据与令牌 audience 的公开基础 URLaudienceNoneOCI API audience可选issuer_urlbase_url服务器自身的 OAuth 元数据 issuer注意这是 FastMCP 自己的身份不影响上游 OCI 的 issuerrequired_scopes[openid]令牌校验所需 scope 下限在 token 校验时强制检查redirect_path/auth/callbackOCI 集成应用中配置的重定向路径allowed_client_redirect_urisNone允许 MCP 客户端使用的重定向 URI 模式列表client_storage内存客户端注册与令牌的存储后端生产建议用 Redis 等持久化存储jwt_signing_key自动生成FastMCP 签发自身令牌的签名密钥require_authorization_consentTrue是否要求授权确认可设为remember/externalenable_cimdTrue是否启用 CIMDClient ID Metadata Document对 URL 型 client ID 的支持两个值得注意的实现细节scope 处理OCIProvider._prepare_scopes_for_token_exchange会在上游授权码换令牌时省略 scope返回空列表因为 OCI IAM 的令牌端点不接受这些 scope而required_scopes仍作为 FastMCP 侧校验的下限保留。身份传播get_access_token()来自 fastmcp.server.dependencies可在工具函数内取回当前登录用户的令牌用于后续 OCI 控制面身份传播。进阶令牌交换调用 OCI 控制面 API认证完成后你拿到的是OCI IAM 域访问令牌它无权直接调用 OCI 控制面Control PlaneAPI。若需要以登录用户身份操作 OCI 资源而非使用服务账号必须将 IAM 域令牌交换为 OCIUPSTUser Principal Session Token再创建TokenExchangeSigner签名器用它构造 OCI 服务客户端。5.1 配置身份传播信任Identity Propagation Trust在 OCI CLI 中执行以下命令创建信任关系先用你的实际值替换IAM_GUID与CLIENT_ID通常可复用前面创建的那个 OAuth 客户端oci identity-domains identity-propagation-trust create \ --schemas [urn:ietf:params:scim:schemas:oracle:idcs:IdentityPropagationTrust] \ --public-key-endpoint https://IAM_GUID.identity.oraclecloud.com/admin/v1/SigningCert/jwk \ --name For Token Exchange --type JWT \ --issuer https://identity.oraclecloud.com/ --active true \ --endpoint https://IAM_GUID.identity.oraclecloud.com \ --subject-claim-name sub --allow-impersonation false \ --subject-mapping-attribute username \ --subject-type User --client-claim-name iss \ --client-claim-values [https://identity.oraclecloud.com/] \ --oauth-clients [CLIENT_ID]5.2 在服务端实现签名器工厂在 MCP 服务器中加入如下代码完整示例见 OCIProvider 模块 docstring以及官方文档 docs/integrations/oci.mdxfrom fastmcp.server.dependencies import get_access_token from fastmcp.utilities.logging import get_logger from oci.auth.signers import TokenExchangeSigner import os logger get_logger(__name__) # 从环境变量加载 OCI_IAM_GUID os.environ.get(OCI_IAM_GUID) OCI_CLIENT_ID os.environ.get(OCI_CLIENT_ID) OCI_CLIENT_SECRET os.environ.get(OCI_CLIENT_SECRET) _global_token_cache {} # 内存缓存tokenID - signer def get_oci_signer() - TokenExchangeSigner: authtoken get_access_token() tokenID authtoken.claims.get(jti) token authtoken.token # 命中缓存则直接返回 cached_signer _global_token_cache.get(tokenID) if cached_signer: logger.debug(fUsing globally cached signer for token ID: {tokenID}) return cached_signer # 未命中则创建新的 OCI signer logger.debug(fCreating new signer for token ID: {tokenID}) signer TokenExchangeSigner( jwt_or_functoken, oci_domain_idOCI_IAM_GUID.split(.)[0] if OCI_IAM_GUID else , client_idOCI_CLIENT_ID, client_secretOCI_CLIENT_SECRET, ) _global_token_cache[tokenID] signer logger.debug(fSigner cached for token ID: {tokenID}) return signer拿到signer对象后即可用它创建任意 OCI 控制面服务客户端实现登录用户身份 → OCI 资源操作的完整身份传播。需要注意示例中的_global_token_cache仅为演示用途生产环境应替换为线程安全如threading.Lock保护或分布式缓存实现。生产环境配置持久化令牌与加密存储默认情况下OCIProvider的客户端注册与令牌存储在内存中服务器重启即丢失。生产部署应同时配置jwt_signing_key与client_storageimport os from fastmcp import FastMCP from fastmcp.server.auth.providers.oci import OCIProvider from key_value.aio.stores.redis import RedisStore from key_value.aio.wrappers.encryption import FernetEncryptionWrapper from cryptography.fernet import Fernet auth_provider OCIProvider( config_urlos.environ.get(OCI_CONFIG_URL), client_idos.environ.get(OCI_CLIENT_ID), client_secretos.environ.get(OCI_CLIENT_SECRET), base_urlos.environ.get(BASE_URL, https://your-production-domain.com), # 生产环境令牌管理 jwt_signing_keyos.environ[JWT_SIGNING_KEY], client_storageFernetEncryptionWrapper( key_valueRedisStore( hostos.environ[REDIS_HOST], portint(os.environ[REDIS_PORT]) ), fernetFernet(os.environ[STORAGE_ENCRYPTION_KEY]) ) ) mcp FastMCP(nameProduction OCI App, authauth_provider)配置要点jwt_signing_key与client_storage协同工作确保令牌与客户端注册在服务器重启后仍然有效务必用FernetEncryptionWrapper包裹存储后端对 OAuth 令牌进行静态加密——否则令牌将以明文存储敏感值一律放在环境变量中分布式部署使用 Redis 等持久化后端。验证与排障单元测试tests/server/auth/providers/test_oci.py 覆盖了OCIProvider初始化行为断言了 client ID/secret、authorization/token 端点、JWTVerifier 的 audience 与 required_scopes、redirect path 等关键状态可作为你理解参数语义和排查配置问题的参考。认证失败排查优先检查三项——环境变量是否已导出且无多余空格、OCI 控制台重定向 URL 是否与redirect_path完全一致、客户端应用是否已Activate。OCIProvider 构造报错构造时会实时请求 discovery URL若域名写错或网络不通会因 10 秒超时机制快速失败而非无限阻塞。小结通过本示例你可以在约半小时内完成 OCI IAM Identity Domain → FastMCP 服务器 的完整 OAuth 安全接入OCI 控制台注册 Confidential Application → 配置三个环境变量 → 用OCIProvider保护工具 → 浏览器登录验证。若服务需要调用 OCI 控制面再叠加令牌交换即可实现用户身份传播。相关的完整参考实现与文档均可在当前仓库中找到示例目录、OCIProvider 源码、OIDCProxy 基类 与 官方集成文档。【免费下载链接】fastmcp The fast, Pythonic way to build MCP servers and clients.项目地址: https://gitcode.com/GitHub_Trending/fa/fastmcp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价