AI应用普遍存在认证/授权混淆问题:登录时验证一次身份,之后全程视为白名单;授权应发生在每个操作前,传统Web的粗粒度检查在AI时代不再安全。
我在 AI 应用评审中反复看到这样一种失败模式:应用只在登录时精确地检查一次"你是谁",之后就把 Agent 当作拥有空白支票——在整个会话期间畅通无阻。读个文件,没问题。发封邮件,没问题。删条记录,为什么不行,你二十分钟前才登录的。这不是授权模型,这是一个伪装成授权模型的登录界面。
Authentication 和 Authorization 不是同一个问题问两遍,它们是两个完全不同的问题,而大多数 AI 应用只回答了第一个,然后在整个会话期间悄悄地、永远地跳过了第二个。
Authentication 发生一次,在门口:你是谁。应用检查密码、会话 Cookie、SSO 令牌,或者其他什么,然后得到满足。到这里没问题,这部分大多数团队实际上做得对。
Authorization 应该持续发生,在建筑物内的每扇门上:既然我们知道这是谁了,现在,这个特定资源上的这个特定动作,应该被允许吗?这就是 AI 应用基本上都跳过的部分。传统的 Web 应用之所以能够粗粒度地检查授权,是因为人类是点击按钮的人,很慢,每一步都有自然的摩擦。AI Agent 没有这样的摩擦。它可以在三秒钟内链接十五个工具调用,如果你的授权模型是"好吧,他们登录了",那这十五个调用中的每一个都继承了同一张空白支票。

假设你的 AI 助手已经过 Authentication,是一名支持工程师,有权读取客户工单。在它的工具列表某处,还有一个"run_sql_query"工具,因为六个月前有人调试时需要它,但没人移除它。Authentication 层看到一个有效的、已登录的支持工程师。它没有"这个特定工具调用,在这个特定表上,为了这个特定原因,现在"的概念。所以 Agent 运行了查询。不是因为有人决定支持工程师应该为那个任务拥有那个访问权限,而是因为没有人构建本可以阻止它的层。
这正是 RBAC 和更好的 scoped OAuth 令牌应该弥合的差距,也是当一个团队用一个长期存在的服务账户"为了简单起见"连接 Agent 时,会被悄悄重新引入的差距。

差异并不奇特。Agent 发出的每个工具调用都应该携带一个 scope,另一端应该在每次实际执行任何操作之前真正检查那个 scope,而不仅仅是在会话开始时检查一次。这正是 OAuth 2.0 scopes 的构建目的,也是更新的 Rich Authorization Requests 规范(RFC 9396)进一步扩展的内容,允许你在"读取此项目中的工单"级别表达授权,而不是平面的"读取工单,所有工单,无处不在"。
以下是一次性门版本的大致情况,不幸的是,这接近许多 Agent 框架的默认值:
# Checked once, at session start, then trusted for everything after
def handle_tool_call(session, tool_name, args):
if session.is_authenticated:
return execute_tool(tool_name, args)
raise PermissionError("not logged in")
以及按操作检查的版本,其中令牌的 scope 实际针对特定工具调用尝试执行的操作进行了检查:
def handle_tool_call(session, tool_name, args):
token = session.access_token # short lived, scoped, from the OAuth flow
required_scope = TOOL_SCOPE_MAP[tool_name] # e.g. "tickets:read"
if required_scope not in token.scopes:
raise PermissionError(f"token lacks scope: {required_scope}")
if not resource_matches_scope(args, token):
# e.g. token is scoped to project_id=42, but the call targets project_id=17
raise PermissionError("resource outside token's authorized scope")
if token.is_expired():
raise PermissionError("token expired, re-authorize")
return execute_tool(tool_name, args)
第二个版本有更多代码,但那些检查每一个都在回答第一个版本从未提出的问题。哪个工具,在哪个资源上,在哪个仍有效的授权下。
RFC 6749,OAuth 2.0 Authorization Framework,基础 scope 模型。
RFC 9396,OAuth 2.0 Rich Authorization Requests,用于比平面 scope 字符串更细粒度地表达授权。
NIST SP 800-207,Zero Trust Architecture,本文真正只是它的一个具体案例:不要仅仅因为请求来自已认证的会话就信任它,要为所执行的特定操作再次验证。
让人登录,或者让 Agent 登录,只回答了一个问题,而这个问题不是"这应该发生吗"。如果你的 AI 应用的整个授权模型是"好吧,会话是有效的",那你根本没有授权,你有的只是一个穿着更大外衣的 Authentication。每次都检查操作,而不仅仅是行动者;每次都检查,而不仅仅是在门口。
Akash Devdhar 是一位高级软件工程师,专攻企业身份、身份验证、授权和 AI 基础设施。他撰写关于使用 OAuth、OIDC、RBAC 和现代身份架构构建安全 AI 系统的文章。