curl --request POST \
--url https://api.ayrshare.com/api/hook/webhook/secret \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--header 'Profile-Key: YOUR_PROFILE_KEY' \
--data '{
"secret": "your-new-signing-secret"
}'
{
"status": "success",
"action": "webhook",
"refId": "3dc079614bdc3f281d9" // User Profile Ref Id
}
Webhooks
署名シークレットのローテーション
24 時間のデュアル署名グレースウィンドウで Webhook 署名シークレットを安全にローテーションします
POST
/
hook
/
webhook
/
secret
curl --request POST \
--url https://api.ayrshare.com/api/hook/webhook/secret \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--header 'Profile-Key: YOUR_PROFILE_KEY' \
--data '{
"secret": "your-new-signing-secret"
}'
{
"status": "success",
"action": "webhook",
"refId": "3dc079614bdc3f281d9" // User Profile Ref Id
}
概要
Ayrshare はすべての Webhook 配信について、署名シークレット をキーとしてペイロードの HMAC-SHA256 で署名します。これにより、受信側は配信が本当に Ayrshare からのものであることを確認できます。検証の仕組みについては Webhook セキュリティ を参照してください。 署名シークレットをローテーションすると、定期的なスケジュールで、あるいは漏洩が疑われる場合には即座に置き換えることができます。ローテーションを安全に行うため、Ayrshare はローテーション後に 24 時間のグレースウィンドウ を開き、その間の配信は 以前のシークレットと新しいシークレットの両方 で署名されます。これにより、1 件も配信を落としたり拒否したりすることなく、独自のスケジュールで受信側を更新できます — Stripe や GitHub と同じパターンです。署名シークレットは プロファイル全体で共通 です。1 つの User Profile (UID) につき
1 つのシークレットがあり、そのプロファイルが登録している すべて の Webhook アクションに
署名します。アクションごとの署名シークレットは存在しません — シークレットを設定または
ローテーションすると、そのプロファイルのすべてのアクションで一度に変更されます。
ダッシュボードからローテーションする
Developer Dashboard の Webhooks ページ から署名シークレットを設定またはローテーションできます。プロファイルに少なくとも 1 つの Webhook が登録されると、Webhook リストの上に Signing Secret パネルが表示されます。1
Signing Secret パネルを開く
Webhooks ページ に移動します。シークレットがまだ設定されていない場合、パネルには No signing secret configured と Set Signing Secret ボタンが表示されます。すでに設定されている場合は、Signing secret configured と Rotate ボタンが表示されます。
2
設定またはローテーション
Set Signing Secret(初回)または Rotate(既存のシークレット)をクリックします。強力でランダムに生成されたシークレットがあらかじめ入力され、表示された状態でモーダルが開きます。Copy でコピー、Regenerate で新しいものを生成、または paste my own を切り替えて独自の値を指定できます。
3
確認
シークレットを安全な場所にコピーしてください — 一度しか表示されず、UI から再取得することはできません — その後、確認して送信します。成功トーストが表示され、パネルが更新されます。
4
受信側を更新
ローテーション時(初回設定ではない場合)、パネルにはアクティブなグレースウィンドウのインジケーターが表示され、ウィンドウが閉じるまで Rotate ボタンは無効になります。新しいシークレットを受信側にデプロイするための時間は 24 時間です。
API 経由でローテーションする
1 回の呼び出しで署名シークレットをローテーション(または設定)します。これにより、新しいシークレットが作成され、プロファイルのシークレット参照がそれに向け直され、既存のシークレットが存在した場合には、置き換えられたシークレットが 24 時間後に期限切れとなる「以前のシークレット」として記録されます。ヘッダーパラメータ
ボディパラメータ
string
必須
新しい署名シークレットの値です。空でない任意の文字列を受け付けます。長く、高エントロピーなランダム値(たとえば 32 バイトのランダムを base64url エンコードしたもの)を推奨します。
curl --request POST \
--url https://api.ayrshare.com/api/hook/webhook/secret \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--header 'Profile-Key: YOUR_PROFILE_KEY' \
--data '{
"secret": "your-new-signing-secret"
}'
{
"status": "success",
"action": "webhook",
"refId": "3dc079614bdc3f281d9" // User Profile Ref Id
}
secret はレスポンスで 決して 返されず、ログにも残りません。レスポンスには、クライアント向けの refId(UID のハッシュ)が含まれ、UID そのものは決して含まれません。Profile-Key ヘッダーは任意で、マルチプロファイルアカウントにおいて、ローテーションを単一の User Profile にスコープします。
secret が欠落または空の場合は、マップされたエラー(code: 101、“Missing/incorrect parameter”)が HTTP 400 ステータスとともに返され、現在のシークレットには変更が加えられません。API 経由の初回設定(既存のシークレットなし)では、以前のシークレットは記録されず、グレースウィンドウなしでシークレットが作成されます。
安全なローテーション手順
24 時間のグレースウィンドウがあるため、操作の順序に厳密な決まりはありません — 受信側は全期間を通じて動作し続けます。推奨される手順は次のとおりです:1
シークレットをローテーション
ダッシュボードまたは API 経由でローテーションします。Ayrshare は直ちに、以前のシークレットと新しいシークレットの両方で配信に署名し始めます。
2
受信側を更新
24 時間以内に、新しいシークレットで検証を行うよう Webhook 受信側にデプロイします。
3
ウィンドウを閉じる
24 時間後、Ayrshare は以前のシークレットを自動的にクリアし、新しいシークレットのみで署名します。お客様側での追加作業は不要です。
グレースウィンドウがまだ開いている間に再度ローテーションすると、直前に置き換えられた
シークレットが新しい「以前のシークレット」となり、新たな 24 時間のウィンドウが始まります。
一度に保持される「以前のシークレット」は 1 つだけです。
グレースウィンドウ中の署名検証
グレースウィンドウ外では、署名された配信は標準のヘッダーを持ちます(Webhook セキュリティ を参照):X-Authorization-Timestamp : <Unix Timestamp In Seconds>
X-Authorization-Content-SHA256 : <current-sig>
X-Authorization-Content-SHA256-V2 : v1=<current-sig>
X-Authorization-Content-SHA256-V2 ヘッダーには 両方 の署名が、現在の署名を先頭にカンマ区切りで列挙されます:
X-Authorization-Timestamp : <Unix Timestamp In Seconds>
X-Authorization-Content-SHA256 : <current-sig>
X-Authorization-Content-SHA256-V2 : v1=<current-sig>,v1=<previous-sig>
X-Authorization-Content-SHA256 は変更されません: 後方互換性のため、常に
現在のシークレットによる単一の HMAC を保持します。デュアル署名は新しい
X-Authorization-Content-SHA256-V2 ヘッダーにのみ表示されます。X-Authorization-Content-SHA256-V2 の各値には、スキームタグが接頭辞として付きます。v1= は、X-Authorization-Content-SHA256 と全く同じように計算される HMAC-SHA256 署名を示します。-V2 ヘッダーは配信が署名されるときには常に存在し、少なくとも v1=<current-sig> を保持するため、安定した受信側のコントラクトとして依拠できます。
ローテーション中(またはローテーション外で)配信を検証するには:
1
HMAC を計算
ローカルに設定された署名シークレットを使用して、生のリクエストボディ の HMAC-SHA256 を計算します。
2
列挙されたすべての署名と比較
X-Authorization-Content-SHA256-V2 を読み取り、カンマで分割し、各値から v1= の接頭辞を取り除いて、計算した HMAC が列挙された v1= 署名の いずれか と一致すれば、その配信を本物として受け入れます。v1=<previous-sig> に一致し、新しいシークレットに更新された受信側は v1=<current-sig> に一致します — ウィンドウ中はどちらも成功します。
受信側の検証例
Node.js
import crypto from "crypto";
// secret is the signing secret currently configured on your receiver.
function isAuthenticWebhook(rawBody, headers, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody) // the raw, unparsed request body
.digest("hex");
const headerValue = headers["x-authorization-content-sha256-v2"] || "";
// Accept if ANY v1= signature in the header matches our computed HMAC.
return headerValue
.split(",")
.map((part) => part.trim())
.filter((part) => part.startsWith("v1="))
.map((part) => part.slice("v1=".length))
.some((sig) => {
const sigBuf = Buffer.from(sig);
const expectedBuf = Buffer.from(expected);
// timingSafeEqual throws on length mismatch — treat as not authentic.
return (
sigBuf.length === expectedBuf.length &&
crypto.timingSafeEqual(sigBuf, expectedBuf)
);
});
}
HMAC は必ず、受信した 生の リクエストボディのバイトそのものに対して計算してください
— 再シリアライズした JSON オブジェクトに対してではありません。再シリアライズは
空白やキー順を変えて検証を壊す可能性があります。タイミング攻撃を避けるため、
(
crypto.timingSafeEqual のような)定時間比較を使用してください。