当 AI Agent 开始代表用户读取 GitHub 仓库、向 Slack 频道发消息时,身份问题就不再只是“把一个 Token 塞进环境变量”。系统需要明确回答:谁授予了权限、授予了哪些范围、授权属于哪次 Agent 会话,以及事后如何追踪。
Amazon Bedrock AgentCore Identity 提供的 Consent portal,是一套托管的用户授权页面;配合 AgentCore Gateway 的 session binding endpoint,可以把 GitHub、Slack 等目标的三方 OAuth(3LO)授权绑定到具体会话,并通过 AWS CloudTrail 检查相关活动。
Consent portal 解决的不是登录,而是委托边界
三方 OAuth 中存在三个角色:用户、Agent 应用和 GitHub 或 Slack 这样的资源服务。与服务账号不同,3LO 要求最终用户亲自确认授权范围。
一条典型链路可以概括为:
- Agent 通过 AgentCore Gateway 请求调用 GitHub 或 Slack 工具。
- Gateway 判断当前会话是否已经关联可用的用户授权。
- 如果尚未授权,应用把用户引导到托管的 Consent portal。
- 用户查看目标系统和所需权限,并进入 GitHub 或 Slack 的 OAuth 授权页面。
- OAuth 流程完成后,授权结果通过 session binding endpoint 与当前 Agent 会话建立关联。
- Gateway 在后续工具调用中使用这份与用户、目标和会话相关的授权。
这里最关键的设计不是页面长什么样,而是授权必须绑定到正确的运行上下文。如果只保存一个全局访问令牌,多位用户使用同一个 Agent 时,很容易出现跨用户复用凭证的问题。session binding 则让应用能够围绕“用户—会话—目标授权”建立边界。
配置 GitHub 与 Slack 3LO 时要明确三张清单
部署 Consent portal 之前,建议先整理目标、权限和环境。下面的 YAML 不是 AWS 资源模板,而是一份可以放进项目仓库的配置清单示例;字段需要按实际 AgentCore、GitHub OAuth App 和 Slack App 配置进行映射。
# oauth-targets.example.yaml
# 这是团队内部的配置清单,不是可直接部署的 CloudFormation 模板。
environment: development
consent_portal:
public_base_url: https://consent.example.com
session_ttl_minutes: 30
agentcore_gateway:
gateway_id: replace-with-your-gateway-id
session_binding_endpoint: https://replace-with-managed-binding-endpoint
targets:
github:
oauth_flow: 3LO
client_id_secret_ref: secrets/github/client-id
client_secret_secret_ref: secrets/github/client-secret
redirect_uri: https://consent.example.com/oauth/callback/github
scopes:
- read:user
- repo
slack:
oauth_flow: 3LO
client_id_secret_ref: secrets/slack/client-id
client_secret_secret_ref: secrets/slack/client-secret
redirect_uri: https://consent.example.com/oauth/callback/slack
scopes:
- channels:read
- chat:write
运行前至少要逐项确认:
- 目标清单:Agent 到底需要 GitHub、Slack,还是两者都需要?开发与生产环境应使用不同的 OAuth 应用和回调地址。
- 权限清单:示例中的
repo权限可能过宽。如果 Agent 只读取公开仓库,应选择更窄的权限;Slack 也不应因为“以后可能用到”就申请大量 scope。 - 回调清单:OAuth 服务商登记的 redirect URI 必须与 Consent portal 使用的地址完全一致,同时只允许 HTTPS 生产地址。
- 密钥清单:客户端密钥应进入 Secrets Manager 等密钥系统,不要写入 YAML、镜像或 Agent 提示词。
GitHub 和 Slack 的 scope 语义不同,不要试图用一套抽象权限掩盖差异。更稳妥的方式是让每个工具声明自己真正需要的 scope,再由部署流程汇总并进行安全审查。
把授权入口接入 Agent,而不是提前索取所有权限
应用层适合采用“按需授权”:只有当用户第一次调用需要外部权限的工具时,才展示 Consent portal。这样既能减少无意义的授权,也能让用户理解“为什么现在需要这个权限”。
可以将工具调用状态设计为以下几类:
READY 已有有效且与当前会话绑定的授权
CONSENT_REQUIRED 尚未获得用户授权,应返回 Consent portal 地址
CONSENT_IN_PROGRESS 用户正在完成 GitHub 或 Slack OAuth
CONSENT_DENIED 用户拒绝授权,不应自动重复弹窗
REAUTH_REQUIRED 授权失效、被撤销或权限范围不足
应用处理时要把“拒绝授权”视为正常业务分支,而不是系统异常。例如,用户不愿授予 Slack 写权限时,Agent 可以生成待发送文本,让用户手工复制,而不是不断要求重新授权。
session binding endpoint 的具体请求格式和路径应以实际创建的 AgentCore 资源为准。集成时至少应保留以下关联信息:
- 应用自己的用户标识;
- Agent 会话标识;
- Gateway 或 Agent 标识;
- GitHub、Slack 等目标标识;
- 授权状态和过期时间;
- 用于防止 OAuth 请求混淆与重放的短期状态值。
不要把 OAuth access token 返回给浏览器或写进 Agent 的对话上下文。提示词、模型日志和普通应用日志都不应成为令牌存储介质。
用 CloudTrail 检查谁改了配置、何时发生授权活动
AgentCore Identity 相关活动可以结合 AWS CloudTrail 进行审查。下面的脚本会查询指定时间之后的 CloudTrail 管理事件,并筛选原始事件中包含 agentcore 的记录。
运行前需要安装并配置 AWS CLI 与 jq,同时让当前身份拥有读取 CloudTrail 事件的权限。将区域和开始时间替换为实际值:
#!/usr/bin/env bash
set -euo pipefail
export AWS_REGION="us-east-1"
export START_TIME="2025-01-01T00:00:00Z"
aws cloudtrail lookup-events \
--region "$AWS_REGION" \
--start-time "$START_TIME" \
--max-results 50 \
--output json \
| jq -r '
.Events[]
| select((.CloudTrailEvent | ascii_downcase) | contains("agentcore"))
| [
.EventTime,
.EventName,
(.Username // "unknown"),
((.Resources // []) | map(.ResourceName // "") | join(","))
]
| @tsv
'
如果暂时没有匹配结果,可以先移除 select(...) 查看完整事件,确认当前账户、区域和时间范围是否正确。生产环境还应建立 CloudTrail trail,把事件持续投递到 S3 或日志分析平台,而不是只依赖 lookup-events 的交互式查询。
审计时重点检查:
- 谁创建或修改了 Consent portal 与 OAuth 目标;
- OAuth 客户端配置是否在异常时间被替换;
- 哪个身份修改了 Gateway 或会话绑定相关配置;
- 失败、拒绝和重复授权是否突然增加;
- 开发环境身份是否操作了生产资源。
CloudTrail 主要帮助观察 AWS 侧活动,并不天然覆盖 Agent 在 GitHub 或 Slack 内完成的每个下游动作。完整审计通常还要关联 GitHub 审计日志、Slack 审计日志以及应用自身的工具调用记录。关联时记录请求 ID、会话 ID和目标类型即可,不要复制访问令牌。
上线前的取舍与检查表
托管 Consent portal 减少了自行开发授权页面、回调处理和会话关联的工作,但并不替代权限建模。上线前可以按下面的清单做一次评审:
- 每个工具只申请完成当前动作所需的最小 scope;
- 开发、测试和生产环境使用独立的 OAuth 应用与密钥;
- 授权明确绑定用户、Agent 会话和目标,禁止使用全局共享 Token;
- 用户拒绝授权后,Agent 提供降级方案而不是无限重试;
- 对过期、撤销和 scope 不足分别处理,并允许用户重新授权;
- CloudTrail 已开启长期留存、告警与跨账户保护;
- GitHub、Slack 与应用日志可通过请求 ID 或会话 ID 关联;
- 日志、提示词和浏览器端均不会暴露 OAuth Token。
对于能代表用户执行写操作的 Agent,还应在 OAuth 同意之外增加业务确认。例如,发送 Slack 消息、创建 GitHub Issue 或修改仓库内容前,再展示具体动作和目标对象。OAuth 回答的是“Agent 能不能做”,而业务确认回答的是“用户这一次是否真的要做”。