Skip to main content

账号、配置与 OAuth 登录

finch.settings、API Key 与两条 OAuth 路径

需要用户凭据的小工具有三条路径,按凭据类型选择。

结构化配置:finch.settings

manifest 声明字段,Finch 在工具箱详情页原生渲染,用户保存后自动重载小工具:

{
  "settings": {
    "fields": [
      { "key": "endpoint", "type": "string", "label": "Endpoint" },
      { "key": "maxItems", "type": "number", "label": "最大条数", "default": 10 },
      { "key": "region", "type": "select", "label": "区域",
        "options": [{ "value": "us", "label": "US" }, { "value": "eu", "label": "EU" }] }
    ]
  }
}

代码里 ctx.settings.get('endpoint') 只读取,不能写入。字段类型:stringnumberbooleanselectliststring 可标 secret: true(密码框)或 multiline: true(多行)。

API Key / Token

用《标准化 UI》里的模态框表单收集,存入 ctx.secrets。manifest 需声明允许的密钥名:

{ "permissions": { "secrets": ["apiKey"] } }

入口放哪里:ComposerAction 菜单、容器设置菜单(见《Session 容器》)、或一个 setup_* 工具。优先前两者——它们不依赖模型主动调用工具。

OAuth 路径 A:小工具自己持有 provider

用于调用普通 HTTPS API(Google、GitHub 等)。manifest 声明 provider id:

{ "permissions": { "oauth": ["google"] } }

代码定义 provider 并发起流程:

const google: finch.OAuthProviderConfig = {
  id: 'google',
  name: 'Google',
  icon: 'assets/google.png',              // 包内 PNG,显示在授权弹窗
  clientId: PUBLIC_CLIENT_ID,             // 发布者预先注册的公开 Client ID
  authorizationEndpoint: 'https://accounts.google.com/o/oauth2/v2/auth',
  tokenEndpoint: 'https://oauth2.googleapis.com/token',
  scopes: ['https://www.googleapis.com/auth/gmail.readonly'],
  resourceOrigins: ['https://gmail.googleapis.com'],  // HTTPS 白名单
};

await ctx.oauth.connect(google);
const status = await ctx.oauth.getStatus(google);
const res = await ctx.oauth.request(
  google,
  'https://gmail.googleapis.com/gmail/v1/users/me/profile',
);
await ctx.oauth.disconnect(google);

Finch 负责浏览器交互、加密存储、刷新加锁、Authorization 头注入。

安全边界(必须理解):

  • 只用 Authorization Code + PKCE 公开客户端,不要内嵌 client secret
  • Access / refresh token 不会跨进程进入小工具,只能通过 ctx.oauth.request() 代理调用。
  • resourceOrigins 是 HTTPS 白名单,不在名单内的地址会被拒绝。
  • request() 会剥离调用方自带的 AuthorizationCookieHostProxy-Authorization 头。
  • 凭据按小工具隔离存储,互相不可见。
  • OAuthResponse.body 是字符串,先判断 HTTP 状态再解析;不要记录可能含隐私的响应体。

Device Flow:GitHub 这类 Web Flow 需要 secret 的服务,设 flow: 'device_code' 并提供 deviceAuthorizationEndpoint,Finch 负责展示、复制用户码并轮询令牌端点。

OAuth 客户端由发布者注册和维护,公开 Client ID 随包分发,不要让终端用户自己去申请 OAuth 应用。icon 强烈建议配置,否则授权弹窗没有品牌标识。

oauth

OAuth 路径 B:OAuth 保护的 MCP server

远程 MCP 端点要求 OAuth 时,不要走路径 A。声明 contributes.mcpServers[].oauth,由 MCP Client 完成 discovery、动态客户端注册(DCR)、PKCE 和 token 生命周期——你无需注册任何 OAuth 客户端,也不需要 permissions.oauth。品牌图标通过 mcpServers[].oauth.providerIcon 提供。

判断法则:同一个服务同时声明了 permissions.oauthmcpServers[].oauth,一定是选错了路径。

登录状态怎么呈现

推荐组合:容器设置菜单里放一行 disabled 的状态行 + 一行可点击的登录/退出行。后台登录状态变化时调 notifyUpdate() 让菜单立即刷新。详见《Session 容器》。