跳至內容
文件 · Webhook

Webhook

環境中一有事情發生,Usher 就能立即通知你的伺服器:有人加入、登入、更改資料或離開。每個事件都是一個傳送到你所選地址的已簽署 POST 請求;如果你的伺服器沒有回應,就會再試一次。

加入端點

在 Usher Console 中打開環境,然後選擇 Webhook → 新增端點。提供一個你的 https:// 地址,並選擇它要接收的事件。Console 只會顯示一次端點的簽署機密(whsec_…):請將它與伺服器的其他機密存放在一起。

事件時機
user.created有人建立了帳户
user.updated帳户有所變更:電郵、姓名、驗證狀態或停權(包括你組織的目錄透過 SCIM 執行的停權)
user.deleted帳户已刪除
session.created有人登入
session.ended工作階段結束:已登出、遭撤銷或提前到期

傳送測試會將一個 webhook.test 事件只傳送到該端點,不論它訂閱了哪些事件。

收到的內容

請求
POST /usher/webhooks HTTP/1.1
content-type: application/json
user-agent: Usher-Webhooks/1
webhook-id: msg_2fk7x…
webhook-timestamp: 1793643116
webhook-signature: v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE=
內文
{
  "type": "user.created",
  "timestamp": "2026-11-02T18:11:56.412Z",
  "data": {
    "user": {
      "id": "Qz3m…",
      "email": "lena@acme.com",
      "emailVerified": false,
      "name": "Lena Live",
      "image": null,
      "banned": false,
      "createdAt": "2026-11-02T18:11:56.380Z",
      "updatedAt": "2026-11-02T18:11:56.380Z"
    }
  }
}

事件描述的是用户和工作階段,絕不包含機密:沒有權杖、沒有密碼雜湊、沒有角色,也不會說明某人為什麼遭到停權。

檢查每一次傳遞

Usher 按照 Standard Webhooks 規格簽署,因此它的任何程式庫都能替你檢查簽名。請拒絕任何無法通過驗證的內容。這些程式庫也會拒絕時間戳記相差超過五分鐘的請求,因此舊的傳遞內容無法被重送。

app/usher/webhooks/route.ts
// a route that receives Usher's webhooks (Node, the standardwebhooks package)
import { Webhook } from 'standardwebhooks'

const wh = new Webhook(process.env.USHER_WEBHOOK_SECRET!) // whsec_…, from Usher Console

export async function POST(request: Request) {
  const body = await request.text() // the raw body: the signature covers it byte for byte
  let event: { type: string; timestamp: string; data: Record<string, unknown> }
  try {
    event = wh.verify(body, Object.fromEntries(request.headers)) as typeof event
  } catch {
    return new Response('bad signature', { status: 400 })
  }
  // webhook-id is the same on every attempt: skip one you have handled already
  if (await alreadyHandled(request.headers.get('webhook-id')!)) return new Response(null, { status: 204 })
  await queue(event) // answer quickly; do the work afterwards
  return new Response(null, { status: 204 })
}
  • 在 15 秒內回應,回傳任何 2xx 狀態碼。其他任何回應(包括重新導向)都會視為失敗。
  • 預期會重複:一則訊息在每次嘗試中都保有相同的 webhook-id;已經處理過的就略過。
  • 不要依賴順序:重試可能在較新的事件之後才送達。

當你的伺服器沒有回應

Usher 會按順序在 5 秒、5 分鐘、30 分鐘、2 小時、5 小時、10 小時和 10 小時後再試(總共大約一天半),之後便會放棄。Console 的傳遞記錄會顯示每則訊息的每次嘗試,以及你伺服器的最後一次回應,而重新傳送會從頭開始一次傳遞。

新的機密

在 Console 中按下 新機密,會產生另一個機密並只顯示一次。在接下來的 24 小時內,每次傳遞都會帶有兩個簽名,每個機密各一個,讓你可以部署新機密而不漏掉任何內容。之後就只有新機密會簽署。

傳遞的來源

Webhook 會經由 Usher 的對外連線代理送出,而該代理不會連線到私人或內部地址。端點必須是公開名稱上的 https:// 地址:不能是 IP 地址、私人名稱,或 Usher 自己網域上的地址。