En Onay REST API platformu, gelen SMS kodlarını bekleme yapmaksızın anında iletmek için HMAC-SHA256 imzalı Webhook bildirim mimarisini destekler. Türkiye ve dünya genelindeki geliştiriciler için uçtan uca veri bütünlüğü, anlık OTP teslimatı ve sahte istek önleme standartları sunan kurumsal altyapımızla sistemlerinizi üst düzeyde güvenceye alın.
Giriş: Polling Yönteminin Maliyetleri ve Webhook İhtiyacı
Geleneksel API mimarilerinde SMS kodunu beklemek için her 3-5 saniyede bir GET isteği (polling) göndermek, yüzlerce aktif işlemde sunucular üzerinde gereksiz TCP/TLS el sıkışması, yüksek bant genişliği ve CPU israfı yaratır.
En Onay Webhook Altyapısı, ilgili sanal numaraya SMS ulaştığı milisaniyede uygulamanızın tanımladığı HTTP/HTTPS uç noktasına anlık bildirim (push event) gönderir. Ancak genel internete açık bir Webhook uç noktası, sahte istek (spoofing) ve araya girme (tampering) saldırılarına karşı mutlaka kriptografik imza doğrulaması ile korunmalıdır.
1. HMAC-SHA256 Güvenlik Mimarisi Nasıl Çalışır?
En Onay sunucusu, webhook payload gövdesini (raw JSON) geliştirici panelinizden tanımladığınız gizli anahtar (Webhook Secret) ile HMAC-SHA256 algoritmasından geçirerek bir imza üretir. Bu imza ve isteğin gönderildiği zaman damgası HTTP başlıklarında sunucunuza iletilir:
X-EnOnay-Signature: Üretilen SHA256 hex özeti (Örn:sha256=a5b3...)X-EnOnay-Timestamp: İstek oluşturulma UNIX zaman damgası (Örn:1730000000)
# En Onay'dan gelen örnek Webhook HTTP POST isteği:
curl -X POST https://api.siteniz.com/webhooks/enonay \
-H "Content-Type: application/json" \
-H "X-EnOnay-Timestamp: 1730034120" \
-H "X-EnOnay-Signature: sha256=d3b07384d113edec49eaa6238ad5ff00" \
-d '{
"event": "sms.received",
"activation_id": 9845120,
"phone": "+905510000000",
"service": "whatsapp",
"code": "492018",
"full_sms": "WhatsApp dogrulama kodunuz: 492-018",
"received_at": "2026-10-27T10:45:00Z"
}'
2. Python (FastAPI) ile Timing-Safe HMAC Doğrulama
Python ortamında zamanlama saldırılarına (timing attacks) engel olmak için standart == operatörü yerine daima hmac.compare_digest kullanılmalıdır:
import hmac
import hashlib
import time
from fastapi import FastAPI, Request, HTTPException, status
app = FastAPI()
WEBHOOK_SECRET = "sk_live_enonay_secret_key_99"
TOLERANCE_SECONDS = 300 # 5 dakikadan eski istekleri reddet (Replay koruması)
@app.post("/webhooks/enonay")
async def handle_enonay_webhook(request: Request):
signature_header = request.headers.get("X-EnOnay-Signature", "")
timestamp_header = request.headers.get("X-EnOnay-Timestamp", "")
if not signature_header or not timestamp_header:
raise HTTPException(status_code=400, detail="Eksik güvenlik başlıkları")
# 1. Zaman Aşımı / Replay Attack Kontrolü
try:
req_time = int(timestamp_header)
if abs(time.time() - req_time) > TOLERANCE_SECONDS:
raise HTTPException(status_code=403, detail="Zaman damgası geçersiz veya eski")
except ValueError:
raise HTTPException(status_code=400, detail="Geçersiz timestamp biçimi")
# 2. Raw Body ile HMAC-SHA256 Hesabı
raw_body = await request.body()
computed_signature = hmac.new(
key=WEBHOOK_SECRET.encode("utf-8"),
msg=raw_body,
digestmod=hashlib.sha256
).hexdigest()
expected_signature = signature_header.replace("sha256=", "")
# 3. Sabit Zamanlı Karşılaştırma
if not hmac.compare_digest(computed_signature, expected_signature):
raise HTTPException(status_code=401, detail="HMAC imzası geçersiz! Yetkisiz istek.")
payload = await request.json()
activation_id = payload.get("activation_id")
sms_code = payload.get("code")
print(f"[GÜVENLİ BİLDİRİM] Aktivasyon {activation_id} için OTP Kodu: {sms_code}")
# İş mantığınızı burada tetikleyin (Database update, WebSocket bildirim vb.)
return {"status": "ACK", "received": True}
3. Node.js (Express) ile Raw Body Doğrulama Mimarisi
Express sunucularında en yaygın hata, JSON ayrıştırıcısının gövdeyi değiştirmesidir. HMAC doğrulaması mutlaka sunucuya gelen ham (raw) buffer üzerinden yapılmalıdır:
import express from 'express';
import crypto from 'crypto';
const app = express();
const WEBHOOK_SECRET = process.env.ENONAY_WEBHOOK_SECRET || 'sk_live_secret';
// Raw body buffer saklama middleware
app.use('/webhooks/enonay', express.raw({ type: 'application/json' }));
app.post('/webhooks/enonay', (req, res) => {
const signature = req.headers['x-enonay-signature'];
const timestamp = req.headers['x-enonay-timestamp'];
if (!signature || !timestamp) {
return res.status(400).json({ error: 'Eksik güvenlik başlığı' });
}
// Replay attack koruması (300 saniye)
const now = Math.floor(Date.now() / 1000);
if (Math.abs(now - parseInt(timestamp, 10)) > 300) {
return res.status(403).json({ error: 'İstek zaman aşımına uğramış' });
}
// HMAC Hesabı
const hmac = crypto.createHmac('sha256', WEBHOOK_SECRET);
hmac.update(req.body);
const expected = 'sha256=' + hmac.digest('hex');
// Sabit Zamanlı Karşılaştırma
const sigBuffer = Buffer.from(signature);
const expBuffer = Buffer.from(expected);
if (sigBuffer.length !== expBuffer.length || !crypto.timingSafeEqual(sigBuffer, expBuffer)) {
return res.status(401).json({ error: 'İmza doğrulanamadı' });
}
const payload = JSON.parse(req.body.toString('utf-8'));
console.log(`[VERIFIED] SMS Kodu: ${payload.code} - Servis: ${payload.service}`);
return res.status(200).json({ success: true });
});
app.listen(3000, () => console.log('Webhook sunucusu 3000 portunda dinliyor'));
Webhook uç noktanızı yapılandırırken IP filtrelemesi eklemek istiyorsanız, En Onay Geliştirici Dokümanları sayfasında listelenen kurumsal giden IP adreslerini güvenlik duvarınızın izin listesine (whitelist) ekleyebilirsiniz.