Webhook'lar, üçüncü taraf hizmetlerden gerçek zamanlı güncellemeler almanın en güçlü yollarından biridir. Stripe, GitHub, Shopify veya Twilio'dan gelen tek bir HTTP POST, uygulamanızdaki kritik iş mantığını tetikleyebilir — bir müşteriyi ücretlendirme, bir depoyu güncelleme, bir siparişi gönderme veya onay SMS'i gönderme gibi.
Ancak her webhook isteği genel internet üzerinden gelir. Bu da, webhook URL'nizi tahmin eden veya bulan herkesin tamamen meşru görünen kötü niyetli yükler gönderebileceği anlamına gelir. Uygun kimlik doğrulama olmadan, uygulamanız gerçek bir olay ile sahte bir olay arasındaki farkı ayırt edemez.
İşte tam da bu noktada webhook imza doğrulaması devreye girer. Gelen her webhook isteğinin beklediğiniz hizmetten geldiğini ve iletim sırasında değiştirilmediğini garanti eden basit, standartlaştırılmış bir mekanizmadır.
Bu kapsamlı rehberde, webhook imza doğrulamasının tam olarak nasıl çalıştığını ve popüler dillerde nasıl doğru bir şekilde uygulanacağını öğreneceksiniz. Ayrıca kaçınmanız gereken yaygın hataları ve her şeyi uçtan uca nasıl hızlı ve güvenilir bir şekilde test edeceğinizi de göreceksiniz.
Webhook İmza Doğrulaması Nedir?
Webhook imza doğrulaması, gelen bir webhook isteğinin gerçekten beklediğiniz hizmetten geldiğini ve üzerinde oynanmadığını doğrulama sürecidir.
Çoğu sağlayıcı, SHA-256 veya SHA-512 ile HMAC (Karma Tabanlı Mesaj Kimlik Doğrulama Kodu) kullanır. Hizmet şu şekilde hesaplama yapar:
signature = HMAC-SHA256(secret_key, payload)
Daha sonra imzayı bir başlıkta (genellikle X-Signature, Signature veya X-Hub-Signature-256) gönderirler.
Sunucunuz:
- Yükü ham bayt olarak alır (önemli!)
- Sakladığınız sırrı kullanarak HMAC'i yeniden hesaplar
- Hesaplanan imzayı alınan imzayla karşılaştırır
Eğer tam olarak eşleşiyorlarsa, webhook'u işlersiniz. Aksi takdirde, HTTP 401 veya 403 döndürürsünüz.
HMAC-SHA256 Neden Endüstri Standardıdır?
Sağlayıcılar, HMAC-SHA256'yı iyi nedenlerle tercih ederler:
- Hızlı: Mütevazı donanımlarda bile son derece hızlıdır.
- Güvenli: SHA-256, 2025 yılında hala kırılmamıştır.
- Basit: Tek bir gizli anahtar, yönetilecek açık/özel anahtar çiftleri yok.
- Standartlaştırılmış: Her dildeki kütüphaneler bunu doğru bir şekilde uygular.
GitHub, Stripe, Shopify, Slack ve düzinelerce diğer platformların hepsi HMAC-SHA256 kullanır.
Node.js'de Webhook İmza Doğrulaması Nasıl Uygulanır?
Node.js'de gerçek dünya bir örnekle başlayalım.
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const hmac = crypto.createHmac('sha256', secret);
const computedSignature = hmac.update(payload).digest('hex');
return crypto.timingSafeEqual(
Buffer.from(computedSignature),
Buffer.from(signature)
);
}
Dikkat edilmesi gereken ana noktalar:
- Zamanlama saldırılarını önlemek için daima
crypto.timingSafeEqualkullanın. - Dizeler üzerinde asla
===kullanmayın — bu savunmasızdır. - Sabit zamanlı karşılaştırma sağlamak için
Buffer.from()kullanın.
Express middleware örneği:
app.post('/webhooks/stripe', (req, res, next) => {
const signature = req.headers['stripe-signature'];
const secret = process.env.STRIPE_WEBHOOK_SECRET;
// Get raw body (Express needs middleware to preserve raw body)
const rawBody = req.rawBody || req.body; // use body-parser with verify option
if (!verifyWebhookSignature(rawBody, signature, secret)) {
return res.status(401).send('Invalid signature');
}
// Signature is valid → process the event
next();
});
Python Uygulaması (FastAPI + Pydantic)
from fastapi import FastAPI, Request, HTTPException
import hmac
import hashlib
app = FastAPI()
def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
computed = hmac.new(
secret.encode(),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(computed, signature)
@app.post("/webhooks/github")
async def github_webhook(request: Request):
signature = request.headers.get("X-Hub-Signature-256")
if not signature:
raise HTTPException(status_code=401, detail="Missing signature")
payload = await request.body()
if not verify_signature(payload, signature.split('=')[1], SECRET):
raise HTTPException(status_code=401, detail="Invalid signature")
# Process webhook
return {"status": "ok"}
Geliştiricilerin Yaptığı Yaygın Hatalar (ve Bunlardan Nasıl Kaçınılır)
1. JSON.stringify() veya Ayrıştırılmış Gövde Kullanımı
Birçok framework JSON'ı otomatik olarak ayrıştırır. Bu, boşluklar, anahtar sırası ve biçimlendirme farklılıkları nedeniyle doğrulamayı bozar.
Çözüm: Ayrıştırmadan önce daima ham gövdeyi yakalayın.
Express'te: body-parser'ı { verify: true } ile kullanın
FastAPI'da: await request.body() kullanın
2. Dizeleri === ile Karşılaştırmak
Zamanlama saldırıları bilgi sızdırabilir. crypto.timingSafeEqual veya hmac.compare_digest kullanın.
3. Kodda Gizli Bilgileri Saklamak
Ortam değişkenlerini veya gizli bilgi yöneticilerini (AWS Secrets Manager, HashiCorp Vault vb.) kullanın.
4. Tekrar Saldırılarını Yönetmeyi Unutmak
Çoğu sağlayıcı bir zaman damgası içerir. Olayın yakın zamanda gerçekleştiğini kontrol edin (örn. 5 dakika içinde).
const timestamp = req.headers['X-Signature-Timestamp'];
if (Date.now() - timestamp > 5 * 60 * 1000) {
return res.status(401).send('Timestamp too old');
}
5. SHA-1 Kullanımı (Hala Oluyor!)
GitHub, 2022'de SHA-1'i kullanımdan kaldırdı. Her zaman SHA-256 kullanın.
Apidog ile Webhook İmza Doğrulamasını Test Etme
Webhook'ları manuel olarak test etmek zahmetlidir. Bir istek gönderir, günlükleri kontrol eder, düzeltir ve tekrarlarsınız.
Apidog bunu çok kolaylaştırır:
Apidog projenizde, sol kenar çubuğundaki + simgesine tıklayın ve "Diğer Protokol API'leri Oluştur" > "Webhook" seçeneğini seçin.
Webhook'u oluşturduktan sonra, düzenleyicide aşağıdaki alanları doldurun:İstek Metodu: GenelliklePOST.Webhook adı: Bu, API dokümantasyonunda ve OpenAPI dışa aktarımında görünecektir, örn: sipariş.Hata Ayıklama URL'si (isteğe bağlı): Test istekleri göndermek için kullanılan gerçek URL. Not: Bu sadece test amaçlıdır ve dokümantasyona dahil edilmeyecektir.Diğer Bilgiler: İstek gövdesi gibi.
Tüm gerekli alanları doldurduktan sonra Kaydet'e tıklayın.
Webhook URL'nizi Hata Ayıklama URL'si alanına girmeniz ve ardından bir Webhook çağrısını simüle etmek için Gönder'e tıklamanız yeterlidir.
Apidog'un webhook simülatörüyle saatlerce süren hata ayıklama süresinden tasarruf ettim. Hatta Stripe'ın tam stripe-signature formatını ve GitHub'ın sha256=... önekini bile destekliyor.
Gerçek Dünya Örneği: Stripe Webhook'larını Doğrulama
Stripe özel bir başlık formatı kullanır:
stripe-signature: t=1681234567,v1=abc123...,v0=def456...
Şunları yapmalısınız:
t=zaman damgasını çıkarınv1=imzasını çıkarın (tercih edilen)payload + timestampkullanarak yeniden hesaplayın- Sadece
v1kısmını karşılaştırın
Stripe, bu karmaşıklığı yönetmek için resmi kütüphaneler sağlar:
const stripe = require('stripe')('sk_...');
stripe.webhooks.constructEvent(payload, sigHeader, endpointSecret);
Ancak, kendiniz uygulamanız gerektiğinde temel HMAC'i anlamak çok önemlidir.
Gelişmiş Konular: Birden Fazla İmzayı Tolere Etme
Bazı sağlayıcılar (Stripe gibi) geriye dönük uyumluluk için birden fazla imza gönderir. Kodunuz şunları yapmalıdır:
- Başlığı
,ile ayırın - Her birini deneyin
- Herhangi biri eşleşirse kabul edin
2025 Yılında Güvenlik İçin En İyi Uygulamalar
- Webhook sırlarını her 90 günde bir değiştirin.
- Mümkün olduğunda kısa ömürlü sırları kullanın.
- Başarısız doğrulamaları günlüğe kaydedin ancak asla sırrı günlüğe kaydetmeyin.
- Kaba kuvvet saldırılarını önlemek için webhook uç noktalarını hız sınırlamasına tabi tutun.
- Her zaman HTTPS kullanın.
Sonuç: Küçük Bir Doğrulama Adımı, Büyük Bir Güvenlik Kazancı
Webhook imza doğrulaması önemsiz bir detay gibi gelebilir. Ancak bu, güvenli bir uygulama ile saldırganların kolayca istismar edebileceği bir uygulama arasındaki farktır.
Bunu doğru bir şekilde uygulayın, Apidog gibi araçlarla kapsamlı bir şekilde test edin ve entegrasyonlarınızın korunduğunu bilerek daha rahat uyuyun.
Apidog'u bugün ücretsiz indirin ve ilk webhook'unuzu 5 dakikadan daha kısa sürede doğrulayın. Kodunuzun gerçekten çalıştığını kanıtlamanın en hızlı yoludur.
