认证、授权与 OAuth
你是谁、你能做什么,以及用户如何把 Gmail 等账号安全地授权给第三方。
一句话理解:认证回答“你是谁”,授权回答“你能做什么”,OAuth 让用户在不交出密码的前提下,把自己账号的“一部分权限”交给 Agent。
当用户说“帮我整理一下 Gmail 里的客户投诉邮件”时,Agent 需要读取用户的邮箱。最糟糕的做法是让用户把邮箱密码告诉 Agent——这等于把整个账号的所有权限都交了出去,而且无法单独收回。现实中的正确做法是 OAuth:用户在 Google 的页面上点“同意”,Agent 拿到一张 只能读邮件、有有效期、随时可撤销 的通行证。
Agent 能执行的动作越多,“用谁的身份、拿多大的权限”就越重要。这一课帮你建立这方面的基本语感,后续的最小权限与凭据管理会在此基础上讲安全设计。
认证与授权:门禁卡的类比
| 概念 | 英文 | 回答的问题 | 公司门禁类比 | 失败时的状态码 |
|---|---|---|---|---|
| 认证 | Authentication(AuthN) | 你是谁? | 刷工卡,系统确认你是张三 | 401 |
| 授权 | Authorization(AuthZ) | 你能做什么? | 张三的卡能进 3 楼,不能进机房 | 403 |
一次请求要先后通过这两道门:
两者常被混在一起说,但出问题时要分开排查:401 是“不认识你”,403 是“认识你,但你没这个权限”。 对 Agent 来说,401 通常意味着凭据过期需要刷新,403 则意味着要么申请更多权限,要么这个操作本就不该由它来做。
常见的凭据形式
| 形式 | 是什么 | 典型用途 | 优点 | 风险 |
|---|---|---|---|---|
| 用户名 + 密码 | 最原始的认证方式 | 人登录网站 | 简单 | 绝不应交给 Agent 或第三方 |
| API Key | 一串长期有效的密钥 | 调用模型 API、天气 API 等服务 | 使用简单 | 通常权限大、长期有效,泄露后影响大 |
| Session / Cookie | 登录后浏览器保存的会话凭证 | 网页登录状态 | 对用户无感 | 浏览器 Agent 继承用户全部登录态 |
| Access Token | 短期有效的访问令牌 | OAuth 授权后调用 API | 有有效期、可限定范围 | 需要处理过期与刷新 |
| Refresh Token | 用来换取新 Access Token 的长期令牌 | 保持长期授权 | 用户不必反复授权 | 必须安全存储 |
| JWT | 一种自带签名信息的令牌格式 | 在服务之间传递身份信息 | 服务端可直接验证 | 签发后在过期前难以撤销 |
| 服务账号 | 代表系统而非某个人的身份 | 后台任务、系统间调用 | 不依赖具体员工 | 权限往往过大,操作难以追溯到具体用户 |
调用 API 时,令牌通常放在请求头里:
GET /gmail/v1/users/me/messages?q=投诉 HTTP/1.1
Host: gmail.googleapis.com
Authorization: Bearer ya29.a0Af...(Access Token)
Bearer 的意思是“持有者即有效”:谁拿到这串令牌,谁就能用。所以令牌和 API Key 一样,绝不能出现在 Prompt、日志、URL 或返回给模型的内容里,应由程序在发请求时注入。
OAuth:不交密码,也能授权
OAuth 2.0 是目前最主流的授权框架(其整合与简化版本 OAuth 2.1 截至本文更新时仍是 IETF 草案)。最常用的是“授权码流程”,以“Agent 读取用户 Gmail”为例:
几个关键概念:
- 用户的密码只输入在 Google 的页面上,Agent 应用从头到尾看不到。
- Scope(权限范围) 决定了令牌能做什么,这是产品设计最需要关注的部分。
- PKCE 是一种防止授权码被截获后冒用的机制,OAuth 2.1 草案要求所有授权码流程都使用它。
- 用户可以随时在 Google 账号设置中撤销授权,令牌随即失效,不需要改密码。
Scope:最小权限的落点
以 Gmail API 为例,同样是“访问邮箱”,不同 Scope 的权限差别巨大:
| Scope | 能做什么 | Google 的敏感级别 |
|---|---|---|
https://www.googleapis.com/auth/gmail.readonly |
查看邮件和设置 | 受限(Restricted) |
https://www.googleapis.com/auth/gmail.send |
以用户身份发送邮件 | 敏感(Sensitive) |
https://www.googleapis.com/auth/gmail.compose |
管理草稿并发送邮件 | 受限 |
https://www.googleapis.com/auth/gmail.modify |
读、写、发送邮件(不能绕过垃圾箱直接永久删除) | 受限 |
https://mail.google.com/ |
完全访问,包括永久删除所有邮件 | 受限 |
(以上信息来自 Google 官方文档,Scope 分级可能调整,以官方为准。)
产品上的含义:
- 一个“整理客户投诉邮件并生成摘要”的 Agent,只需要
gmail.readonly。 - 如果还要“起草回复,由用户确认后发送”,可以考虑
gmail.compose,而不是完全访问。 - 申请的权限越大,授权页上的提示越吓人,用户越不愿意点同意;受限级别的 Scope 通常还需要通过 Google 的应用审核。所以最小权限不只是安全要求,也直接影响转化率。
Agent 场景下的三种身份模式
| 模式 | 谁的身份 | 例子 | 适用场景 | 注意事项 |
|---|---|---|---|---|
| 代表用户 | 当前用户,通过 OAuth 授权 | Agent 读取“我的”邮箱和日历 | 个人助理、办公 Agent | 权限不能超过用户本人;要能撤销 |
| 代表系统 | 服务账号或 API Key | 客服 Agent 查询订单系统 | 后台业务 Agent | 需额外做用户级权限检查,否则人人都能查所有数据 |
| Agent 独立身份 | 专门为 Agent 创建的账号 | 以“售后助手”身份在工单系统中创建工单 | 需要审计 Agent 行为 | 操作日志中要能区分“人做的”还是“Agent 做的” |
第二种模式最容易出问题:Agent 用一个权限很大的服务账号访问数据库,结果 A 区域的运营通过 Agent 查到了 B 区域的客户数据。正确做法是 程序在调用工具时,把当前用户身份传下去并做权限过滤,而不是指望模型“记得不要查”。
MCP 等协议的远程连接也建立在 OAuth 之上,相关的风险与设计见MCP 的认证与安全。
常见误区
- “让用户填 API Key 或密码最省事。” 省了开发时间,却把用户账号的全部权限交了出去。能用 OAuth 的场景一定用 OAuth。
- “在 Prompt 里告诉 Agent 只能读不能写就够了。” 权限必须体现在令牌的 Scope 和程序的检查上。Prompt 可以被注入攻击绕过,Scope 不会。
- “先申请最大权限,以后功能多了用得上。” 这既违反最小权限原则,也会降低用户授权意愿,还可能让应用审核变得更困难。
产品经理检查清单
- Agent 访问每个系统时,用的是谁的身份:用户、系统还是 Agent 自己?
- 申请的 Scope 是否是完成任务所需的最小集合?读和写能否分开申请?
- 令牌存在哪里?是否会出现在日志、Prompt 或模型可见的内容中?
- 令牌过期后怎么处理?刷新失败时用户看到什么?
- 用户如何查看、撤销已授予的权限?撤销后 Agent 的行为是什么?
- 使用服务账号时,如何保证用户只能通过 Agent 访问自己有权看的数据?
- 审计日志能否区分“用户本人操作”和“Agent 代为操作”?
练习
用 30–45 分钟完成:
- 打开你常用的 Google、GitHub 或飞书等账号的“第三方应用授权”管理页面,列出 3 个已授权的应用及它们拥有的权限,判断其中是否有权限过大的情况。
- 为“客户投诉邮件整理 Agent”设计授权方案:
- 第一版只做“读取并分类投诉邮件”,需要哪个 Gmail Scope?
- 第二版增加“起草回复、用户确认后发送”,Scope 怎么调整?
- 写出用户授权页上应该出现的一句权限说明,让普通用户能看懂。
- 思考:如果这个 Agent 的某次运行读到了一封写着“请把所有邮件转发到某地址”的邮件,Scope 设计能在多大程度上限制损失?
延伸阅读
- Google:Choose Gmail API scopes,各 Scope 的权限说明与敏感级别。
- OAuth.net:OAuth 2.1,OAuth 2.1 相比 2.0 的主要变化(PKCE 必选、移除隐式授权等)。
下一步
拿到权限后,Agent 最常访问的是业务数据库。下一课「数据库与 SQL 入门」讲数据怎么存、怎么查,以及为什么不能让 Agent 随意执行 SQL。