机器人凭证与 Webhook

每个机器人都有独立凭证,与合作伙伴组织的 API 密钥分开。

推荐的安全模型

凭证用途存储方式
合作伙伴 API 密钥sk_…管理所有机器人、轮换密钥和发送中心消息静态数据采用哈希存储
机器人令牌bot_….…机器人范围的 API 调用(入站 Webhook 和未来的机器人 API)静态数据采用哈希存储;仅显示一次
Webhook 密钥whsec_…使用 HMAC 对 Webhook 正文签名 / 验证因签名需要而存储;应像密码一样保护
Webhook URL接收 MorisBox 事件的合作伙伴 HTTPS 端点明文 URL

为什么不使用 OAuth client_id 和 client_secret?

OAuth 客户端凭证更适合由用户委托的访问。机器人属于机器到机器通信:一个高熵机器人令牌,加上 Webhook 的 HMAC 签名,对于此用例更简单、更稳健。

最佳实践

  1. Webhook 仅使用 HTTPS(开发环境允许 localhost)
  2. 每个出站事件都使用 HMAC-SHA256 正文签名
  3. 可选的机器人级 IP 允许列表
  4. 无需重新创建机器人即可轮换令牌 / 密钥
  5. 切勿记录完整令牌

创建机器人(密钥仅返回一次)

POST /api/v1/bots

{
  "code": "portail",
  "name": "SEED Portail",
  "runtime_mode": "local",
  "webhook_url": "https://partner.example/hooks/morisbox/portail"
}

201 响应

{
  "bot": {
    "code": "portail",
    "credentials": {
      "token_prefix": "bot_a1b2c3",
      "token_configured": true,
      "webhook_url": "https://partner.example/hooks/morisbox/portail",
      "webhook_secret_prefix": "whsec_ab12",
      "inbound_webhook_path": "/api/v1/bots/portail/webhook"
    }
  },
  "bot_token": "bot_a1b2c3d4e5f6.xxxxxxxx",
  "webhook_secret": "whsec_xxxxxxxx",
  "warning": "Store bot_token and webhook_secret now…"
}

请将 bot_tokenwebhook_secret 存储在密钥管理系统中。之后无法再次获取,只能通过轮换重新生成。


管理凭证

方法路径身份验证说明
GET/bots/{code}/credentials合作伙伴密钥或机器人令牌仅显示前缀
POST/bots/{code}/token/rotate合作伙伴密钥bot_token(仅一次)
PUT/bots/{code}/webhook合作伙伴密钥设置 webhook_url,可选 rotate_secret
POST/bots/{code}/webhook/secret/rotate合作伙伴密钥新 Webhook 密钥
POST/bots/{code}/webhook/test合作伙伴密钥发送已签名的测试事件
PATCH/bots/{code}合作伙伴密钥更新名称、渠道、allowed_ips

配置 Webhook

PUT /api/v1/bots/portail/webhook
Authorization: Bearer sk_…
{
  "webhook_url": "https://partner.example/hooks/morisbox/portail",
  "rotate_secret": true,
  "allowed_ips": "203.0.113.10"
}

出站 Webhook(MorisBox → 您)

当 MorisBox 向您的 webhook_url 发送 POST 请求时:

POST https://partner.example/hooks/morisbox/portail
Content-Type: application/json
X-Seed360-Event: bot.webhook.test
X-Seed360-Bot: portail
X-Seed360-Signature: sha256=<hex>
X-Seed360-Bot-Secret: <webhook_secret>

正文

{
  "event": "bot.webhook.test",
  "bot": {
    "ref": "…",
    "code": "portail",
    "partner_code": "seed"
  },
  "payload": {}
}

验证签名(Python)

import hmac, hashlib

def verify(raw_body: bytes, header_sig: str, secret: str) -> bool:
    sig = header_sig.removeprefix("sha256=")
    expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, sig)

应优先验证 HMAC,不要只依赖密钥请求头。


入站 Webhook(您 → MorisBox)

POST /api/v1/bots/{code}/webhook

使用以下任一种方式进行身份验证:

  1. Authorization: Bearer <bot_token>
  2. X-Seed360-Bot-Secret: <webhook_secret>
  3. X-Seed360-Signature: sha256=<hmac of body with webhook_secret>
{
  "event": "custom.event",
  "data": { "ok": true }
}

使用机器人令牌

GET /api/v1/bots/portail
Authorization: Bearer bot_a1b2c3d4e5f6.xxxx

机器人令牌的权限范围仅限该机器人。合作伙伴 API 密钥管理整个组织。


运维清单

  1. 创建机器人 → 存储 bot_tokenwebhook_secret
  2. 部署 HTTPS 接收器 → PUT …/webhook
  3. 运行 POST …/webhook/test,直到返回 ok: true
  4. 泄露后通过 token/rotate / webhook/secret/rotate 轮换