基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
  • 知识卡片碎片时间过考点
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
    • AI 热点每日 AI 资讯与动向
AI 工作台
简历
旧版
AIHT
内容
精选全部 AI 动态热点榜AI 日报收藏
分类
模型行业编程产品技术观点开源
更多
Agent 接入
返回首页开发者导航
AIHT
精选 / 资讯详情
8.0
热点
AI SCORE
技术实践2026-11-03 14:31

用令牌交换实现 Agent 用户委托

dev.to · AI#Agent#OAuth2#身份认证
Editor brief · 编辑速览

文章介绍连接 PingFederate 与 Entra 的令牌代理,以 RFC 8693 令牌交换承接 Agent 的用户委托。设计区分目标资源所需令牌,并集中处理 Entra 权限范围与委托链。

文章思维导图
Knowledge map
拖拽缩放
AI deep read

AI 深度解读

AI agent 要访问邮件、日历和业务 API,难点不只是拿到 token:它代表谁、能做什么、出了问题怎么追责,都得一起回答。直接借用用户权限容易放大授权,统一用服务账号又容易丢失发起人的身份。

作者用 ping-entra-broker 在 PingFederate 和 Microsoft Entra ID 之间加了一层令牌代理,通过 RFC 8693 统一接收授权交换请求。值得借鉴的是它把身份、资源和权限收进同一套检查流程;但这篇只讲入口设计,还不足以证明整条授权链已经安全闭环。

一次 API 调用,要同时说明用户和 agent 是谁

原文的用户通过 PingFederate(PF)登录,PF 再通过 OIDC 与 Entra 联邦对接。agent 调用下游时,需要解决两类凭证问题:PF 保护的资源需要接受 PF token,并保留委托链;Graph 等资源需要 audience 和 scope 正确的 Entra token。

audience 表示 token 发给哪个服务,scope 表示允许执行哪些操作。仅仅确认「用户登录过」,无法回答「这个 agent 能不能替他读邮件」。

RFC 8693 的 token exchange 给请求划出了三个位置:subject token 表示借用谁的访问身份,actor token 表示谁在执行,resource 表示目标资源。其中 resource 参数采用 RFC 8707 的定义。

下面的请求把三者放进同一个交换入口:

POST /broker/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:token-exchange
&subject_token=<the user's PF access token>
&subject_token_type=urn:ietf:params:oauth:token-type:access_token
&actor_token=<the agent's signed client assertion>
&actor_token_type=urn:ietf:params:oauth:token-type:jwt
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=<the same signed assertion>
&resource=https://graph.microsoft.com
&scope=User.Read

要看的是 actor_token 和 client_assertion:这里复用了同一份签名断言,分别承担执行者声明和客户端认证的角色。它们没有代替用户的 subject_token。

broker 会检查断言的 audience,避免截获的断言被拿到其他服务兑换;还会存储每份断言的 jti,拒绝重复使用。作者明确说,他们发现重放检查能阻止同一份断言被兑换两次。不过,原文没有提供测试过程或覆盖范围。

另一个边界是,agent 不持有用户的 Entra refresh token,也不自行拼接 Entra scope 字符串。这些细节集中交给 broker,减少每个 agent 各写一套刷新和交换逻辑的机会。

资源白名单,比 agent 自己声明权限更可信

agent 提交资源 URI,并不代表 broker 就会相信它。真正决定放行的是一份带版本的 YAML resource map,它记录资源、租户、Entra audience、scope 和交付方式。

下面的配置同时展示了资源上限和 agent 上限:

version: 1
resources:
  - resource: https://api.contoso.com/orders
    type: api
    tenant: 11111111-1111-1111-1111-111111111111
    entra_audience: api://orders-api
    scopes: [orders.read, orders.write]
    delivery: { default: proxy, allow_token_mode: false }
    max_hops: 2
    method_scopes: { GET: orders.read, PATCH: orders.write, DELETE: orders.write }
    rebac:
      required: true
      object_from: path
      object_type: order
      relations: { GET: viewer, PATCH: editor, DELETE: owner }

  - resource: https://graph.microsoft.com
    type: api
    tenant: home
    entra_audience: https://graph.microsoft.com
    scopes: [User.Read, Mail.Read]
    delivery: { default: token, allow_token_mode: true }
    max_hops: 1

agents:
  - pf_client_id: report-writer
    entra_agent_identity: { home: "00000000-0000-0000-0000-000000000002" }
    allow:
      https://api.contoso.com/orders: [orders.read]
      https://graph.microsoft.com: [User.Read]
    allow_token_mode: true
    max_hops: 2

要看 agents.allow:orders 资源支持 orders.write,不代表 report-writer 就有写权限;Graph 支持 Mail.Read,这个 agent 也仍然只能申请 User.Read。

检查顺序很清楚:资源是否登记、agent 是否获准访问、交付方式是否允许。未知资源直接拒绝,避免一个拼错的 URI 把请求导向意外的 audience。

原文一处说权限取交集,紧接着又强调超额申请会被拒绝。结合示例,准确理解应是:白名单决定权限上限,申请越界时直接报错,不会静默缩减后继续执行。

例如申请 orders.write 会收到符合 RFC 6749 形式的 invalid_scope,拒绝决定也会写入审计日志。

max_hops 则约束 agent 之间的再次委托。样例里 orders 是 2,Graph 是 1,agent 自身是 2。整条链受沿途最小限制约束,每跳也不能扩大上一跳的权限,避免多个 agent 接力把授权越传越宽。

token 交出去以后,控制能力会发生变化

检查通过后,broker 有两种交付方式。

token mode 直接返回 Entra access token,由 agent 调用下游。Graph 示例返回 token_type: Bearer、expires_in: 3599、scope: User.Read 和 delivery: token,issued_token_type 为 urn:ietf:params:oauth:token-type:access_token。其中 3599 是示例值,不能据此推断所有 token 的固定有效期。

这种方式调用直接,但凭证一旦交出,后续请求就不必经过 broker。原文说 bearer token 可以在到期前被使用,不能把它理解成能访问任意服务:前文仍然要求它具有匹配的 audience 和 scope。

proxy mode 则把 Entra token 留在 broker,agent 拿到代理 URL 和代理专用 token,再由 broker 调用业务 API。示例入口是 https://broker.example.com/broker/proxy/orders/orders/1001,使用 curl -sS 和 authorization: Bearer $PROXY_TOKEN 请求;$PROXY_TOKEN 不是 Entra token。

orders 默认采用这种方式,因为每次调用都能经过统一的日志、限流和关系访问控制(ReBAC)检查。大白话解释:有「读订单」权限还不够,还得确认你与这张订单存在允许读取的关系。配置从路径提取对象,把 GET、PATCH、DELETE 分别关联到 viewer、editor、owner。

演示控制台还会生成每一步的 curl 视图,用 $USER_TOKEN 等名称替换真实凭证,便于查看调用结构。

我的判断

我认同它把权限判断从 agent 的临场决策里移出来。相较于每个 agent 自己维护 scope、audience、刷新和重试逻辑,集中入口更容易统一检查;相较于只用服务账号,也更有条件保留用户与执行者的对应关系。

但这是架构经验,作者没有提供维护成本、延迟或故障率的对照数据。集中之后,broker 自身的可用性、refresh token 存储,以及策略更新是否可靠,都会影响整条链。

还有一处不能跳过:配置声明了 ReBAC 规则,不等于已经证明对象级鉴权有效。原文没展开关系数据来源、路径解析和实际校验流程,也把 refresh token 如何换成 agent token、为何需要 agent identity 留给了下一篇。

采用 RFC 8693 能统一交换请求的表达方式,安全边界仍要靠具体实现落实。

能拿来做什么

  • 给 Node agent 接入企业 API 时,可以先建立资源与 agent 的授权表,把资源支持的权限和单个 agent 获准的权限分别列清楚,并明确越界申请的错误行为。
  • 为 token 交换入口检查 subject、actor、resource 是否齐全,同时检查签名断言的 audience 和 jti 防重放,不能只停在验签成功。
  • 对需要逐次审计、限流或对象关系校验的业务 API,可以评估 proxy mode;允许直接返回 token 的资源则应单独登记,并接受后续调用绕过 broker 的控制边界。
  • 调试 agent 授权时,可以参考原文的 curl 展示方式,用变量名代替真实 token,让开发者看清请求结构,同时保留拒绝决策的审计信息。
Original source

本文由 AI 通读原文后重新编写,观点部分为站内判断,细节以原文为准,来源 dev.to · AI,原文版权归原作者所有。

阅读原文
上一篇
Claude Code 更新强化钩子失败处理
下一篇
自托管 Kuru:容器化智能体平台拆解

资讯速览

dev.to · AI · 2026-11-03 14:31

AI 评分 8.0 / 10

相关标签

#Agent#OAuth2#身份认证

继续阅读

  • 视觉模型双引擎部署的显存与输出差异
  • Claude Code 更新强化钩子失败处理
  • 自托管 Kuru:容器化智能体平台拆解
  • 本地小模型跑自动化:格式全对,业务仍错
  • 盘古两款云端模型月底下线,调用方需迁移