Bezpieczeństwo i dostarczanie webhooków
Weryfikacja podpisów webhooków, mechanizm ponownych prób dostarczenia oraz rozwiązywanie problemów.
Dlaczego to ważne
Weryfikacja podpisów potwierdza, że dane są autentyczne i nie zostały zmodyfikowane. Zrozumienie mechanizmu ponownych prób i automatycznego wyłączania pomaga budować odporne integracje.
Weryfikacja podpisów
Każde dostarczenie jest podpisywane za pomocą klucza podpisu przypisanego do endpointu przy użyciu HMAC-SHA256. Podpis obejmuje znacznik czasu oraz treść żądania, co zapobiega atakom powtórkowym (replay attacks).
Podpisywana treść to znacznik czasu w formacie ISO 8601 i treść JSON połączone kropką:
<timestamp>.<body>
Ruby
timestamp = request.headers["X-Webhook-Timestamp"]
signature = request.headers["X-Webhook-Signature"]
body = request.body.read
expected = OpenSSL::HMAC.hexdigest("SHA256", signing_secret, "#{timestamp}.#{body}")
if ActiveSupport::SecurityUtils.secure_compare(expected, signature)
# Signature is valid
else
head :unauthorized
end
Node.js
const crypto = require("crypto");
function verifySignature(signingSecret, timestamp, body, signature) {
const expected = crypto
.createHmac("sha256", signingSecret)
.update(`${timestamp}.${body}`)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}
Python
import hmac
import hashlib
def verify_signature(signing_secret, timestamp, body, signature):
expected = hmac.new(
signing_secret.encode(),
f"{timestamp}.{body}".encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
Zapobieganie atakom powtórkowym
Porównaj wartość X-Webhook-Timestamp z bieżącym czasem i odrzucaj żądania starsze niż 5 minut.
Rotacja klucza podpisu
Kliknij Rotate Secret na stronie szczegółów webhooka, żeby wygenerować nowy klucz podpisu. Poprzedni klucz zostaje natychmiast unieważniony.
Żeby przeprowadzić rotację bez przestoju:
- Wdróż endpoint tak, aby akceptował podpisy zarówno ze starego, jak i nowego klucza
- Wykonaj rotację klucza w Kit
- Sprawdź, czy dostarczenia przebiegają pomyślnie z nowym kluczem
- Usuń stary klucz z endpointu
Dostarczanie i ponowne próby
Kit wysyła ładunek JSON metodą POST do Twojego endpointu z następującymi limitami czasu:
| Ustawienie | Wartość |
|---|---|
| Limit czasu połączenia | 10 sekund |
| Limit czasu odczytu | 15 sekund |
Odpowiedź 2xx oznacza dostarczenie jako zakończone. Wszystko inne to błąd, a sposób jego obsługi przez Kit zależy od tego, czy błąd jest przejściowy, czy trwały.
Błędy przejściowe (z ponawianiem)
Błędy przejściowe to problemy, które prawdopodobnie same ustąpią — Twój endpoint był chwilowo przeciążony, przekroczył limit czasu albo był nieosiągalny. Kit ponawia je do 5 prób z wielomianowym opóźnieniem (każde oczekiwanie dłuższe od poprzedniego).
Błąd jest traktowany jako przejściowy, gdy odpowiedź to:
- HTTP
500–599(błędy serwera) - HTTP
408(Request Timeout) - HTTP
429(Too Many Requests) - Błąd sieci lub przekroczenie limitu czasu (odrzucone połączenie, błąd DNS, timeout odczytu)
| Próba | Zachowanie |
|---|---|
| 1 | Natychmiastowa |
| 2–5 | Wielomianowo rosnące czasy oczekiwania |
Błędy trwałe (bez ponawiania)
Błędy trwałe oznaczają, że samo żądanie jest nie do przyjęcia dla Twojego endpointu i ponawianie nic nie da. Kit od razu oznacza dostarczenie jako błędne i go nie ponawia.
Błąd jest traktowany jako trwały, gdy odpowiedź to dowolny inny status 4xx — na przykład 400, 401, 404 lub 410. Jeśli Twój endpoint zwraca taki kod przez pomyłkę, popraw trasę lub uwierzytelnianie po swojej stronie; Kit ponowi próbę dopiero przy następnym zdarzeniu.
Automatyczne wyłączanie
Po 15 kolejnych nieudanych dostarczeniach (niezależnie od typu zdarzenia) Kit automatycznie wyłącza webhooka.
Po wyłączeniu:
- Dalsze próby dostarczenia nie są podejmowane
- Status zmienia się na Disabled ze znacznikiem czasu
disabled_at
Kliknięcie Resume ponownie aktywuje webhooka. Powoduje to zresetowanie licznika błędów i przywrócenie webhooka do stanu aktywnego.
Logi dostarczania
Każdy endpoint webhooka ma zakładkę Deliveries pokazującą 50 ostatnich dostarczeń. Każdy wpis zawiera:
| Pole | Opis |
|---|---|
| Zdarzenie | Typ zdarzenia, które wywołało dostarczenie |
| Status |
pending, in_progress, completed lub errored
|
| Liczba prób | Liczba prób dostarczenia |
| Nagłówki żądania | Nagłówki wysłane wraz z żądaniem |
| Odpowiedź | Kod statusu HTTP lub komunikat błędu |
| Znacznik czasu | Data i godzina utworzenia dostarczenia |
Statusy dostarczenia
| Status | Znaczenie |
|---|---|
pending |
Utworzone, oczekuje na wysłanie |
in_progress |
W trakcie dostarczania |
completed |
Endpoint zwrócił odpowiedź 2xx
|
errored |
Wszystkie ponowne próby wyczerpane lub endpoint zwrócił błąd trwały (4xx) |
Przechowywanie danych
Logi dostarczania są przechowywane przez 30 dni, a następnie automatycznie usuwane. Jeśli potrzebujesz dłuższego przechowywania, zapisuj ładunki po swojej stronie.
Wymagania dotyczące adresów URL
- Wymagany protokół HTTPS — endpointy HTTP są odrzucane
- Tylko publiczne adresy IP — adresy URL prowadzące do adresów prywatnych (localhost, 10.x.x.x, 192.168.x.x itp.) są blokowane
- Adresy URL są walidowane podczas tworzenia oraz przed każdym dostarczeniem
Rozwiązywanie problemów
| Problem | Przyczyna | Rozwiązanie |
|---|---|---|
| Niezgodność podpisu | Nieprawidłowy klucz podpisu lub treść zmodyfikowana przed weryfikacją | Zweryfikuj podpis na podstawie surowej treści żądania z aktualnym kluczem |
| Przekroczenie limitu czasu dostarczenia | Endpoint potrzebuje więcej niż 15 sekund | Zwróć 200 natychmiast i przetwórz dane asynchronicznie |
| Dostarczenie z błędem bez ponowienia | Endpoint zwrócił trwały 4xx (np. 404, 410) |
Popraw trasę, uwierzytelnianie lub metodę; ponawiane są tylko błędy przejściowe (5xx, 408, 429, sieć/timeout) |
| Webhook automatycznie wyłączony | 15 kolejnych niepowodzeń | Napraw endpoint, a następnie kliknij Resume |
| Adres URL odrzucony | Prywatny adres IP lub protokół HTTP | Użyj adresu HTTPS prowadzącego do publicznego adresu IP |
| Zdarzenia nie są wyzwalane | Webhook wstrzymany lub typ zdarzenia nie jest subskrybowany | Sprawdź status webhooka i zasubskrybowane zdarzenia |
W skrócie
- Skopiuj klucz podpisu ze strony szczegółów webhooka
- Zaimplementuj weryfikację podpisu HMAC-SHA256 w endpoincie
- Odrzucaj żądania ze znacznikami czasu starszymi niż 5 minut
-
Zwracaj kod statusu
2xxw ciągu 15 sekund - Obsługuj ponowne próby w sposób idempotentny (to samo zdarzenie może zostać dostarczone więcej niż raz)
- Monitoruj logi dostarczania pod kątem błędów
- Skonfiguruj alerty na wypadek automatycznego wyłączenia webhooka