Security
Verify that webhook events are genuinely sent by Teachfloor.
Why Verify?
Signature verification ensures:
- Events are genuinely from Teachfloor
- Payloads haven't been tampered with
- Protection against malicious requests
Always verify signatures in production.
How It Works
Teachfloor signs each webhook using HMAC-SHA256:
signature = hash_hmac('sha256', json_payload, secret)
The signature is sent in the Teachfloor-Signature
header.
Getting Your Secret
- Go to Developers → Webhooks
- Select your endpoint
- Click Reveal Signing Secret
- Store securely (never commit to version control)
Implementation
PHP
function verifyWebhookSignature(Request $request, string $secret): bool
{
$payload = $request->getContent();
$signature = $request->headers->get('Teachfloor-Signature');
$generated = hash_hmac('sha256', $payload, $secret);
return hash_equals($generated, $signature);
}
Route::post('/webhooks/teachfloor', function (Request $request) {
$secret = config('services.teachfloor.webhook_secret');
if (!verifyWebhookSignature($request, $secret)) {
return response('Invalid signature', 401);
}
ProcessWebhookJob::dispatch($request->json()->all());
return response('OK', 200);
});
Node.js
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const generated = crypto
.createHmac('sha256', secret)
.update(payload, 'utf8')
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(generated),
Buffer.from(signature)
);
}
app.post('/webhooks/teachfloor',
express.raw({ type: 'application/json' }),
(req, res) => {
const secret = process.env.TEACHFLOOR_WEBHOOK_SECRET;
const signature = req.headers['teachfloor-signature'];
const payload = req.body.toString('utf8');
if (!verifyWebhookSignature(payload, signature, secret)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(payload);
processWebhookEvent(event);
res.status(200).send('OK');
}
);
Important Notes
- Use raw request body (not parsed JSON)
- Use timing-safe comparison (
hash_equals
ortimingSafeEqual
) - Store secrets in environment variables
- Verify before processing