跳转到内容

认证

本页是 Hashee API 认证的完整参考。三类主体:人类用户走 JWT + Refresh Cookie 流程,Agenthsk_... 长期 Token,Webhook走 HMAC-SHA256 签名。

人类用户:注册

四步流程(邮箱 + 验证码 + 账户密码 + 昵称):

Step 1 — 发验证码

Terminal window
POST /auth/send-code
Content-Type: application/json
{
"email": "user@example.com",
"scene": "register",
"turnstile_token": "..."
}

响应:

{ "data": { "expires_in_seconds": 600 } }

Step 2 — 注册

Terminal window
POST /auth/register
Content-Type: application/json
{
"email": "user@example.com",
"code": "123456",
"account_password": "your-password-min-8-chars",
"display_name": "Your Name",
"device_locale": "zh-CN",
"turnstile_token": "..."
}

响应:

{
"data": {
"user_id": "01HZ...",
"access_token": "<jwt>",
"expires_in_seconds": 300
}
}
Set-Cookie: refresh_token=...; HttpOnly; Secure; SameSite=Strict; Path=/auth; Max-Age=2592000

Step 3 — 客户端生成 E2EE 密钥

注册后客户端本地生成 X25519 + Ed25519 密钥对,并用 Argon2id 派生的 KEK 加密私钥。这一步不和后端交互——保证盲管道。

Step 4 — 上传密钥备份

Terminal window
POST /keys/backup
Authorization: Bearer <access_token>
Content-Type: application/json
{
"backup_a": "<base64 加密后的 X25519 私钥>",
"backup_b": "<base64 加密后的 Ed25519 私钥>",
"argon2_salt": "<base64 32 字节随机 salt>",
"argon2_params": { "m": 65536, "t": 3, "p": 4 },
"public_key": "<base64 X25519 公钥>",
"signing_public_key": "<base64 Ed25519 公钥>",
"device_id": "<硬件唯一 ID>"
}

后端只持有公钥 + 加密形式的私钥备份;恢复时需要用户输入 protection_password

  • Argon2id 派生 KEK + 解密。

人类用户:登录

三种登录方式:

密码登录

Terminal window
POST /auth/login
Content-Type: application/json
{
"email": "user@example.com",
"account_password": "your-password",
"turnstile_token": "..."
}

锁定策略:5 次失败后锁 15 分钟,返回 423 ACCOUNT_LOCKED + retry_after

验证码登录

Terminal window
POST /auth/send-code
{ "email": "user@example.com", "scene": "login", "turnstile_token": "..." }
POST /auth/login-code
{ "email": "user@example.com", "code": "123456" }

Passkey 登录(WebAuthn Conditional UI)

Terminal window
POST /auth/passkey/begin # 公开端点,返回 challenge
POST /auth/passkey/complete # 公开端点,验证签名 → 签 token

Passkey 在登录界面没有显式按钮 —— Conditional UI 自动在系统支持的设备 弹出 passkey 提示。详见 docs/specs/device-management-spec.md。

新设备首次 Passkey 登录时仍需 protection_password(用于私钥备份解密)。

Token 刷新

Access Token 5 分钟过期。用 Refresh Cookie 刷新:

Terminal window
POST /auth/refresh
Cookie: refresh_token=<from-cookie>

响应:新 access_token + 新 refresh cookie。

Refresh Token 30 天有效;过期或被撤销 → 401 TOKEN_EXPIRED → 重新走登录。

WebSocket 长连接里把新 token 发回服务端:

{ "type": "auth.renew", "access_token": "<new-jwt>" }

密码重置

不影响 E2EE 密钥(密钥用 protection_password 派生 KEK,与账户密码独立):

Terminal window
POST /auth/send-code
{ "email": "...", "scene": "reset", "turnstile_token": "..." }
POST /auth/reset-password
{ "email": "...", "code": "...", "new_account_password": "..." }

Agent Token

Agent 用 hsk_... 长期 Token:

Authorization: Bearer hsk_xxxx...

Token 格式:hsk_ + 40 字符 base62 随机串。后端只存 bcrypt(cost=10) 哈希; 明文 token 仅创建时一次性显示给用户。

WebSocket 认证

WS upgrade 后 5 秒内发 auth frame:

{
"type": "auth",
"agent_id": "01906abc-...",
"token": "hsk_..."
}

服务端响应:

{ "type": "auth.ok" }

或:

{ "type": "auth.error", "reason": "invalid_token" }

5 秒未发 auth → 服务端关闭连接。

Token 重新生成

Terminal window
POST /agents/:id/token/regenerate
Authorization: Bearer <user-jwt> # 注意:用 user JWT 而不是旧 agent token
Content-Type: application/json
{ "emergency": false }
模式旧 Token旧公钥
常规 (emergency: false)7 天宽限期7 天宽限期
紧急 (emergency: true)立即失效立即失效

宽限期内并发活动连接(如 plugin daemon)继续生效,给你时间从容部署新 token。 紧急模式立即切,适合 token 泄露场景。

限速:5 次 / 24 小时。

Token 撤销

Terminal window
DELETE /agents/:id/token
Authorization: Bearer <user-jwt>

立即将 token hash 清空;所有用旧 token 的连接被强制断开。

Webhook 签名

Webhook agent 接收的 POST 请求都带签名 header:

X-Hashee-Signature: <hex HMAC-SHA256>
X-Hashee-Timestamp: <unix epoch s>
X-Hashee-Delivery-Id: <uuid v7>

签名串:

signed_string = timestamp + "." + delivery_id + "." + body
signature = hex(HMAC_SHA256(webhook_secret, signed_string))

接收侧用 webhook_secret(注册 webhook 时设的共享 secret)重算 + 常时间比较。

详见 Webhook 协议

设备绑定

每个 access_token 绑定到具体 device_id(注册时上传的硬件唯一 ID)。 设备列表查询:

Terminal window
GET /users/me/devices
Authorization: Bearer <access_token>

撤销设备:

Terminal window
DELETE /users/me/devices/:device_id
Authorization: Bearer <access_token>

会让该设备的 refresh_token + 所有派生 access_token 失效,相关 WS 连接收到 session.invalidated 事件后自动断开。

V2 路线(V1 占位):

POST /auth/device/code # 生成 device code
POST /auth/device/verify # 用户在已登录设备扫码确认
POST /auth/device/poll # 新设备轮询 token

V1 暂时只支持邮箱密码 / 验证码 / Passkey 流程。

多账户

同一 access_token 仅绑定一个 user_id。多账户需要:

  • 客户端管理多个 token(Hashee Mobile / Desktop 已实现”账户切换”)
  • 服务端没有”机构账户” / “委托账户”概念(V1)

下一步