学习笔记 · Obsidian

Agent 认证授权与 A2A/MCP 协议

LangChainLangGraphLangSmithMCP

AuthN 与 AuthZ 必须分离

  • @auth.authenticate 是认证中间件:校验请求并返回至少包含稳定 identity 的用户对象。
  • @auth.on 是授权:按资源与动作创建元数据、增加查询过滤或拒绝操作。
  • 更具体的处理器优先,例如 threads.create 覆盖 threads,后者又覆盖全局 handler。策略评审必须按实际匹配顺序,而不是只看全局规则。

Cloud 默认用 x-api-key 验证 LangSmith 身份;自托管 Agent Server 默认可能没有认证,只应位于受保护网络。自定义 Auth 支持 Cloud 与 Self-hosted Deployment,但不自动存在于纯 LangGraph OSS 自建服务器。

单租户资源隔离模式

一个可靠的“用户只能看自己的 Thread”策略同时做两件事:

  1. 创建时把 owner_id=identity 写入 resource metadata。
  2. 读取、搜索、更新、删除时返回同一 metadata filter。

只在 UI 隐藏资源不是授权。搜索/list 也必须过滤,且需要覆盖 Thread、Assistant、Cron、Run creation 等关联动作。授权测试至少包含:无 token、伪造 token、用户 A 访问用户 B、搜索泄漏、通过 Run 间接操作他人 Thread。

Store 与 Thread 不同:Store namespace 由应用定义,handler 接收可变 value。可选择:

  • 显式要求 namespace 第一段等于用户 identity,否则 deny;
  • 在服务端自动把 identity 前缀写入 namespace。

第二种更不易被 Agent 忘记,但调试时看到的是重写后的物理 namespace。无论哪种,都应与 Thread owner filter 组合,形成跨 Thread 长期记忆和会话状态的双重隔离。

真实 OAuth 身份接入

教程从硬编码 token 逐步升级为 Supabase/OAuth2 JWT;Supabase 只是示例,核心流程适用于 OIDC/OAuth provider:客户端登录拿 token → Agent Server 校验签名/issuer/audience/expiry → 生成稳定 identity → AuthZ 过滤资源。

Agent Auth 用于 Agent 代表用户访问外部系统。先在控制面登记 provider 与 callback,再由 Agent 发起 OAuth。凭据应保存在专用凭据服务/密钥存储,不能放入 Graph state、Prompt、Trace 或普通 Store。Self-hosted API URL 使用 /api-host,callback 的公网 origin/base path 必须与 IdP 登记值一致。

OpenAPI 不是安全实现

langgraph.json 的 auth.openapi 只修改 /docs 中的 security schema,便于调用者和代码生成器理解 header/scheme;它不会校验任何请求。实际 handler、网关策略和端到端负向测试缺一不可。Self-hosted 如果保持默认“无 scheme”,必须在 Ingress/API Gateway 层提供等价保护。

MCP 端点

Agent Server 通过 /mcp 使用 Streamable HTTP,把 Assistant 暴露为 MCP Tool。最低文档版本为 langgraph-api>=0.2.3、langgraph-sdk>=0.1.61。

  • Tool name/description/schema 是对外契约,输入/输出 schema 应稳定、最小化,避免把内部完整 State 暴露给任意 MCP Client。
  • MCP session 与用户身份需要显式关联;启用自定义 auth 才能提供用户范围工具。
  • MCP Client 仍是外部调用方:必须执行认证、速率限制、审计、Tool allowlist 和输出脱敏。
  • 不需要时可禁用 MCP,以减少攻击面。

A2A 端点

/a2a/{assistant_id} 实现 Google A2A,最低文档版本为 langgraph-api>=0.4.21,支持 message/send、message/stream 与 tasks/get,并自动提供 Agent Card。

A2A contextId 映射到 thread_id,因此外部 Agent 提供的 context 不能直接当作已授权 Thread。跨 Agent 分布式追踪要传播 trace context,但不要传播原始用户 token。Agent Card 的 skills、输入输出模式和 URL 属于公开能力描述,不应包含内部地址或敏感配置。

生产安全清单

  1. 明确 API Key、终端用户 JWT、Agent OAuth token 三种身份,禁止混为一个凭据。
  2. 验证 JWT 的签名、算法白名单、issuer、audience、expiry,并缓存 JWKS 时处理轮换。
  3. Auth handler 返回稳定且不可由客户端自报的 identity;角色/组织信息来自可信 claim 或后端查询。
  4. 对所有资源的 create/read/search/update/delete/create_run 建立矩阵测试。
  5. 对 Store namespace、Thread metadata、MCP session、A2A context 分别验证跨用户越权。
  6. 不把 token 写入 State、Checkpoint、Store、Trace、异常或日志;下游凭据临用临取。
  7. OpenAPI、Studio 能登录、正常请求成功都不能替代负向授权测试。