A2A权限管理怎么配:代理卡声明与调用方校验实操
A2A 权限管理配置不是给接口加一个固定 Token 就完事。
它需要两处配合:代理卡(Agent Card)里声明自己支持哪种认证、需要什么权限范围;
服务端在收到任务请求时,按调用方身份和任务内容做实际校验。
只写声明不校验,等于把权限说明当摆设;
只做校验不写声明,调用方又不知道该怎么带凭证。
下面按“声明—校验—验证”的顺序讲清楚具体怎么配。
示例使用 HTTP+JSON 绑定和 OAuth2 客户端凭证模式,其他认证方式思路相同。
先明确代理卡里的权限声明字段
Agent Card 是一个公开的 JSON 描述文件,通常放在 /.well-known/agent-card.json。
与权限相关的字段主要是 securitySchemes 和 security。
securitySchemes 定义支持哪些认证方案,security 声明调用代理时需要满足哪些方案。
一个最小示例:
{
"name": "order-agent",
"version": "1.0.0",
"url": "https://agent.example.com/a2a",
"securitySchemes": {
"oauth2": {
"type": "oauth2",
"flows": {
"clientCredentials": {
"tokenUrl": "https://auth.example.com/oauth/token",
"scopes": {
"agent:task": "提交任务",
"agent:read": "读取任务状态"
}
}
}
}
},
"security": [
{ "oauth2": ["agent:task"] }
]
}
这里有两个容易填错的地方:
security是数组,表示“满足其中任意一组即可”,不是全部都要满足。如果希望调用方必须同时具备多个 scope,应写在同一个对象的 scope 数组里。scopes里的键名要与服务端实际校验的 scope 字符串完全一致,大小写和冒号都不能随意改。
服务端校验调用方身份和任务权限
代理卡只是对外说明,真正的权限控制发生在任务端点。
以常见的 HTTP+JSON 绑定为例,服务端收到 POST /a2a 后,建议按以下顺序处理:
- 从
Authorization请求头取出 Bearer Token; - 向认证服务器校验 Token 有效性,或本地验签 JWT;
- 检查 Token 中的
scope是否包含agent:task; - 根据任务内容做二次授权,例如任务涉及读取订单时,再检查调用方是否有该订单的访问权;
- 任一步失败,返回明确的 401 或 403。
一个简化的 Node.js 校验片段:
app.post('/a2a', async (req, res) => {
const auth = req.headers.authorization || '';
const token = auth.startsWith('Bearer ') ? auth.slice(7) : null;
if (!token) return res.status(401).json({ error: 'missing_token' });
try {
const payload = await verifyJwt(token); // 校验签名和过期时间
if (!payload.scope?.includes('agent:task')) {
return res.status(403).json({ error: 'insufficient_scope' });
}
// 继续处理任务
} catch (e) {
return res.status(401).json({ error: 'invalid_token' });
}
});
关键点:401 表示身份未通过,403 表示身份通过但权限不够。
这两个状态码不要混用,否则调用方排查时很难判断是凭证问题还是授权问题。
用 curl 验证配置是否生效
配置完成后,至少验证三种情况。
先获取一个测试 Token(具体命令取决于你的认证服务),然后执行:
# 不带 Token,预期 401
curl -i -X POST https://agent.example.com/a2a \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"tasks/send","id":1}'
# 带有效 Token,预期 200 或任务受理响应
curl -i -X POST https://agent.example.com/a2a \
-H 'Authorization: Bearer ' \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"tasks/send","id":1}'
如果返回 401,检查 Token 是否过期、签名密钥是否与服务端一致;
如果返回 403,检查 Token 的 scope 是否包含代理卡里声明的权限。
验证通过后,再确认代理卡文件本身可公开访问且 JSON 格式合法,可以用 curl -s https://agent.example.com/.well-known/agent-card.json | jq . 检查。
两个容易忽略的边界
第一,代理卡是公开的,不要在 securitySchemes 里写客户端密钥或真实 Token,只写认证端点和 scope 名称。
第二,权限校验要覆盖所有任务方法,不能只保护 tasks/send 而漏掉 tasks/get 或取消任务接口,否则调用方可以绕过权限读取任务状态。
如果代理之间还需要传递用户级身份,建议在任务元数据里携带经过签名的用户标识,由下游代理再次校验,而不是直接信任上游传来的明文用户 ID。
常见问题
代理卡里写了 security,但调用方仍然不带 Token 也能调通,为什么?
说明服务端没有做实际校验,代理卡只是声明文件。
需要在任务端点入口增加认证中间件。
scope 名称对不上会怎样?
认证服务签发的 scope 与服务端校验的字符串必须一致。
对不上时通常返回 403,先打印 Token 解码后的 scope 内容再比对。
多个认证方案怎么选?
security 数组里列出多组方案时,调用方满足任意一组即可。
如果希望强制某一种,就只保留一组。
A2A 权限管理配置的落点始终是“声明清楚、校验到位、状态码准确”。
先把代理卡字段和服务端中间件对齐,再用 curl 覆盖无凭证、有凭证、权限不足三种场景,基本就能确认配置是否真正生效。