跳转到正文
Onevium文档
本页内容

应用密钥、scope 与业务用户隔离

对照真实 UI 和 Gateway 路由选择七种 scope,正确传递业务主体,并完成密钥更换、轮换和撤销。

应用密钥验证什么#

业务后端用 App Key 调用 Gateway;桌面登录、设备连接、入站 Webhook 签名与 App Key 是不同身份通道。

每个业务请求同时包含:

text
Authorization: Bearer <应用密钥>
X-Onevium-Subject: <由业务后端确认的用户主体>

密钥确定 owner、应用和可用 scope;X-Onevium-Subject 指定这个应用内的业务用户。Gateway 不会替你的系统验证该用户是否登录,也不会把请求正文里的 owner_idapp_id 当成授权。

创建和取得密钥#

  1. 打开 渠道 → 外部接入,创建应用或选中已有应用。首次创建应用生成的密钥只显示一次,默认包含全部七种 scope。
  2. 为具体后端创建较小权限的凭据:在选中应用上点击创建 API 密钥
  3. 逐项勾选操作,点击创建;关闭凭据弹窗前保存到后端的凭证存储。
  4. 在应用的凭证与历史 → API 密钥查看密钥前缀、Active/Revoked 状态,以及轮换/撤销入口。这里不会重新显示原密钥全文。

Bearer 填一次展示的完整应用密钥,不能用列表前缀或 key_id 代替;也不要填桌面登录令牌或私有控制令牌。

创建对话框的 “对话接入” 预设实际勾选全部七项;“只读” 勾选四个 :read 项。预设不是为你的业务计算的最小权限,应逐项核对。至少选择一项,未知或重复 scope 不被接受。

只读 API 密钥权限示例:可以查询状态和历史,不能发送消息或启动任务。

图中为预览界面的只读权限演示,使用隔离示例数据;不表示已创建真实密钥或通过真实业务授权验收。

七种真实 scope#

UI 名称API 枚举允许的操作
查看已发布服务endpoints:read列出当前应用的已发布服务
读取会话历史conversations:read列会话、读快照/历史、会话 SSE,以及查询 operation
发送消息和重开会话conversations:write新建会话、发送消息、reset
查看任务状态runs:read查询 run 和 run SSE
提交和停止任务runs:write从服务直接创建 run、取消 run
下载附件resources:read下载当前主体可访问的资源内容
上传附件resources:write预留资源并上传内容

没有 *adminwebhooks:write 这类 App Key scope。conversations:write 包含 reset,且 reset 可以使用 cancel_and_reset 停止本代工作;它不是“只能发文字、不能停止任务”的权限。

Scope 只控制 API 操作类别,不会增加服务已经发布的工具、目录、Skills 或 MCP 能力。请求方不能通过添加 modeltoolsworking_directory 等未知字段来扩权。

每类公开接口需要什么权限#

以下路径均属于 Gateway 的业务 API。除 /health 和单独签名的 Webhook 外,表内接口还要求 App Key 与非空 subject。

方法和路径必需 scope说明
GET /api/v1/agent-endpointsendpoints:read当前应用的已发布服务列表
POST /api/v1/agent-endpoints/{id}/runsruns:write任务型入口
POST /api/v1/conversationsconversations:write创建业务会话
GET /api/v1/conversations?endpoint_id=...conversations:readendpoint_id 用于定位设备
GET /api/v1/conversations/{id}conversations:read快照
GET /api/v1/conversations/{id}/messagesconversations:read分页历史
POST /api/v1/conversations/{id}/messagesconversations:write发送消息
GET /api/v1/conversations/{id}/eventsconversations:read会话 SSE
POST /api/v1/conversations/{id}/resetconversations:write重开上下文
GET /api/v1/runs/{id}runs:read状态和结果
GET /api/v1/runs/{id}/eventsruns:read单次任务 SSE
POST /api/v1/runs/{id}/cancelruns:write停止任务,请求体 {}
GET /api/v1/operations/{id}conversations:read即使 operation 来自 run cancel,也使用这个 scope
POST /api/v1/resourcesresources:write声明 endpoint_id、content_type、size
PUT /api/v1/resources/{id}/contentresources:write上传字节;还需匹配类型、长度和 X-Content-SHA256
GET /api/v1/resources/{id}resources:read返回文件内容,不是资源 JSON 元数据
GET /health不使用 App KeyGateway 健康信息,不证明设备或模型执行成功
POST /api/v1/webhooks/{integration_id}使用 Webhook 签名Webhook 教程,不能只用 App Key 代替签名

创建会话、发送消息、直接创建 run、cancel、reset 和预留资源都需要各自操作的 Idempotency-Key。资源内容 PUT 使用内容哈希与不可变资源约束,不应把它当成创建新资源的重试。

应用和 subject 如何隔离#

同一 owner 下不同应用的服务、会话、任务和资源仍分开。读取已有资源时,会同时核对应用和 subject;换成另一个 subject 读取原用户资源,通常得到 404,不是返回别人的内容。

但 App Key 没有绑定某个 subject:持有密钥的后端有责任填入正确主体。不要直接透传浏览器提交的 X-Onevium-Subject、URL 用户 ID 或表单值。建议从已验证登录态构造稳定内部标识,并在多租户系统中包含租户维度。

下面只是业务后端伪代码,不是 Onevium SDK:

typescript
const user = requireAuthenticatedUser(request); // 你现有的登录校验
const subject = `tenant:${user.tenantId}:user:${user.id}`;
const gatewayHeaders = {
  Authorization: `Bearer ${serverSecrets.oneviumAppKey}`,
  "X-Onevium-Subject": subject
};

subject 必须非空,最多 256 字符且无首尾空白。显示名称和邮箱容易变化,不适合作为持久会话关联。读取、SSE、附件下载和控制操作都要沿用相同主体。

同一应用的不同 API 密钥只在 scope 上有区别,不自动隔离用户或服务。若两个业务系统连密钥持有方都不能互相访问,应使用不同应用,而不是只给同一应用多建两把密钥。

按真实功能选择最小范围#

后端用途起始 scope 集合
仅查询已知 run 的结果runs:read
直接提交独立任务并查结果runs:writeruns:read
创建/续聊,查看历史和结果conversations:writeconversations:readruns:read
在上述会话流程中单独取消 run再增加 runs:write
上传或下载附件分别增加 resources:writeresources:read
需要先让用户选择已发布服务再增加 endpoints:read

请求 operations/{id} 需要 conversations:read。仅配 runs:write + runs:read 可以发起 cancel 并查 run,却不能查询控制操作完成状态;需要这个完整闭环时补上 conversations:read

用真实身份验证一次#

先从凭证存储加载 APP_KEY,把 Gateway 地址和业务主体设置为测试值。下面只读取当前应用的服务,需要 endpoints:read

这里的 GATEWAY_URL 只填网关 origin,不包含末尾 /api/v1 例如界面显示 http://127.0.0.1:48541/api/v1 时,变量填 http://127.0.0.1:48541;下方命令会自行追加 /api/v1,不要重复。

bash
: "${APP_KEY:?Load APP_KEY from your credential store first}"
export GATEWAY_URL='http://127.0.0.1:REPLACE_WITH_API_PORT'
export SUBJECT='docs-test-user'
curl --fail-with-body -sS "$GATEWAY_URL/api/v1/agent-endpoints" \
  -H "Authorization: Bearer $APP_KEY" \
  -H "X-Onevium-Subject: $SUBJECT"

成功应返回 200 和 endpoints 数组。空数组表示这个应用没有可见的已发布服务,不代表需要扩大到管理员权限。

建议用另建的只读测试密钥尝试一项写操作,确认收到 403;再按会话教程用两个测试 subject 检查隔离。这些是你需实际执行的验收,不是本页已完成的测试。

权限不足的示例响应(非实测):

json
{
  "error": {
    "code": "FORBIDDEN",
    "message": "Application scope is not allowed."
  }
}

更换、轮换和撤销密钥#

凭证与历史 → API 密钥找到正确前缀,选择轮换密钥 → 确认轮换,保存新显示的密钥。轮换保留原 scope,并撤销旧密钥;没有给旧密钥保留宽限期

需要平滑切换时使用两把密钥:

  1. 创建 API 密钥,选择新后端需要的 scope。
  2. 将新密钥部署到业务后端,使用原 subject 验证所需读写流程。
  3. 确认所有调用方已切换,再对旧前缀选择撤销密钥 → 确认撤销
  4. 检查旧密钥的新请求被拒绝。若需要减少 scope,也应新建密钥;轮换不会自动缩小旧权限。

撤销影响后续鉴权请求,不等同于取消正在执行的任务。已有 SSE 连接也不是每条事件都重新做密钥鉴权;客户端更换密钥后应主动断开、用新密钥重连。单个任务的停止使用明确的 cancel,完整停用应用是影响整个应用的另一项管理操作。

业务凭据不能管理 Gateway#

当前 V1 业务入口供后端访问:带浏览器 Origin,或跨站 Sec-Fetch-Site 的请求会被拒绝。应由已鉴权的业务后端调用,不把 App Key 发给浏览器。

密钥不放 URL;tokenkeyticket 这类查询参数会被拒绝。Onevium 页面使用的 /api/integrations/cloud/... 是桌面管理桥接地址,不是这里的公开 Gateway API。Node Gateway 的公开 /api/v1/management/** 返回 404,不能给 App Key 增加 scope 来打开它。

远端管理使用独立私有控制通道和令牌;设备连接使用设备身份;Webhook 使用签名。不要混用这几类凭据,远端配置见远端网关

错误与验收重点#

现象先检查什么
401 UNAUTHENTICATEDBearer 格式、正确环境的密钥、是否轮换/撤销、应用是否仍有效
403 FORBIDDEN所需 scope、owner/设备状态,以及是否错误地从浏览器直连
400 INVALID_REQUESTsubject 缺失/无效、URL 放了凭据、请求字段不符合接口
已知 ID 返回 404应用、subject、设备路由和实际 ID 是否匹配
轮换后仍有旧流输出关闭旧 SSE,使用新密钥重连;不要把流输出当成新鉴权成功

真实环境还应检查:最小 scope、跨应用/subject 隔离、密钥轮换后的调用方切换、旧密钥拒绝、设备离线及恢复,以及需要的 HTTPS/SSE/回调路径。

下一步#

回到发布与首次请求,实现业务会话,或配置Webhook 和结果回调