webhook-id: 7c1e2f0a-3b5d-4e8f-9a61-2d4c8b0e5f13
webhook-timestamp: 1790490600
webhook-signature: v1,s0RzLJ1d7Cxd9nwe8pqER9DWy/stEIB+uT9MlGVLlM0=
| Haus |
Hvað það er |
| webhook-id |
Afhendingin, sama gildi og delivery_id í meginhlutanum. Mundu hvaða afhendingar þú hefur afgreitt og svaraðu endurtekningu með 200 án þess að vinna verkið aftur. |
| webhook-timestamp |
Þegar við undirrituðum hana, í heilum sekúndum frá 1970. Hafnaðu öllu sem er meira en fimm mínútum frá þinni eigin klukku, svo ekki sé hægt að senda þér gamla afhendingu aftur. |
| webhook-signature |
v1, síðan base64 HMAC-SHA256 af auðkenninu, tímastimplinum og hráa meginhlutanum tengdu saman með punktum, gert með undirritunarlyklinum þínum. Það geta verið fleiri en ein, aðskilin með bilum. Samþykktu afhendinguna ef eitthvert þeirra passar. |
Undirritunarlykillinn
Hann byrjar á whsec_. Taktu það af og base64-afkóðaðu afganginn: þessi bæti eru HMAC lykillinn, ekki textinn sem þú afritaðir. Hann er sýndur einu sinni, þegar þú tengir webhookið eða ýtir á "New signing key" á Publishing síðunni, og við sendum hann aldrei.
Athugaðu hráan meginhluta
Reiknaðu undirritunina út frá bætunum nákvæmlega eins og þær komu, áður en nokkuð þáttar þær. JSON sem hefur verið afkóðað og kóðað aftur eru ekki sömu bæti, og undirritun þess passar ekki.
PHP
<?php
$raw = getenv('SEONIS_SIGNING_KEY'); // whsec_...
// No key, no deliveries. A missing or empty variable would otherwise become
// an empty HMAC key, and anybody can sign with that.
$secret = is_string($raw) && str_starts_with($raw, 'whsec_')
? base64_decode(substr($raw, strlen('whsec_')), true)
: false;
if ($secret === false || strlen($secret) < 24) {
http_response_code(500);
exit('Signing key not configured.');
}
$id = $_SERVER['HTTP_WEBHOOK_ID'] ?? '';
$timestamp = $_SERVER['HTTP_WEBHOOK_TIMESTAMP'] ?? '';
$header = $_SERVER['HTTP_WEBHOOK_SIGNATURE'] ?? '';
$body = file_get_contents('php://input');
if (! ctype_digit($timestamp) || abs(time() - (int) $timestamp) > 300) {
http_response_code(401);
exit('Too old.');
}
$expected = base64_encode(hash_hmac('sha256', "$id.$timestamp.$body", $secret, true));
$valid = false;
foreach (explode(' ', $header) as $signature) {
[$version, $value] = array_pad(explode(',', $signature, 2), 2, '');
$valid = $valid || ($version === 'v1' && hash_equals($expected, $value));
}
if (! $valid) {
http_response_code(401);
exit('Bad signature.');
}
$delivery = json_decode($body, true);
Node.js
import crypto from 'node:crypto';
import express from 'express';
const app = express();
// No key, no server. An empty variable would otherwise become an empty HMAC
// key, and anybody can sign with that.
const raw = process.env.SEONIS_SIGNING_KEY ?? '';
if (!raw.startsWith('whsec_')) throw new Error('SEONIS_SIGNING_KEY is not set.');
const key = Buffer.from(raw.slice('whsec_'.length), 'base64');
if (key.length < 24) throw new Error('SEONIS_SIGNING_KEY is not a valid key.');
// express.raw keeps the body as the bytes we signed.
app.post('/hooks/seonis', express.raw({ type: 'application/json' }), (req, res) => {
const id = req.get('webhook-id') ?? '';
const timestamp = req.get('webhook-timestamp') ?? '';
const header = req.get('webhook-signature') ?? '';
if (!/^\d+$/.test(timestamp) || Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
return res.status(401).send('Too old.');
}
const expected = crypto.createHmac('sha256', key)
.update(`${id}.${timestamp}.`)
.update(req.body)
.digest();
const valid = header.split(' ').some((signature) => {
const [version, value = ''] = signature.split(',');
const given = Buffer.from(value, 'base64');
return version === 'v1' && given.length === expected.length && crypto.timingSafeEqual(given, expected);
});
if (!valid) return res.status(401).send('Bad signature.');
const delivery = JSON.parse(req.body);
res.json({ ok: true });
});
Eða notaðu safn
Opinber Standard Webhooks söfnin fyrir PHP, JavaScript, Python, Go, Ruby og fleira gera allt þetta í einu kalli. Gefðu þeim undirritunarlykilinn eins og hann var sýndur þér, whsec_ meðtalið.
github.com/standard-webhooks
Eldri hausarnir
Afhendingar bera líka undirritunarleyndarmálið sem bearer token og X-AutoSEO-LT-Signature, HMAC af meginhlutanum einum gert með því leyndarmáli. Þau eru enn send svo endapunktar sem byggja á þeim haldi áfram að virka. Nýr endapunktur ætti frekar að athuga webhook-signature: gamla undirritunin nær hvorki yfir tíma né auðkenni, og lykill hennar fer með hverri beiðni.
AutoSEO, Outrank og BabyLoveGrowth sniðin senda nákvæmlega það sem þær þjónustur sendu, svo þau bera ekki þessa hausa.