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
Należy porównać wartość X-Webhook-Timestamp z bieżącym czasem i odrzucić żądania starsze niż 5 minut.
Rotacja klucza podpisu
Aby wygenerować nowy klucz podpisu, należy kliknąć Rotate Secret na stronie szczegółowej webhooka. Poprzedni klucz zostaje natychmiast unieważniony.
Aby przeprowadzić rotację bez przestoju:
- Wdrożyć endpoint tak, aby akceptował podpisy zarówno ze starego, jak i nowego klucza
- Dokonać rotacji klucza w Kit
- Sprawdzić, czy dostarczenia przebiegają pomyślnie z nowym kluczem
- Usunąć stary klucz z endpointu
Dostarczanie i ponowne próby
Kit podejmuje do 5 prób dostarczenia, gdy endpoint jest niedostępny lub zwraca błąd.
| Próba | Zachowanie |
|---|---|
| 1 | Natychmiastowa |
| 2-5 | Wielomianowo rosnące czasy oczekiwania |
| Ustawienie | Wartość |
|---|---|
| Limit czasu połączenia | 10 sekund |
| Limit czasu odczytu | 15 sekund |
Odpowiedź 2xx oznacza dostarczenie jako zakończone. Każdy inny kod statusu lub przekroczenie limitu czasu oznacza dostarczenie jako błędne i uruchamia ponowną próbę.
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 posiada zakładkę Deliveries prezentującą 50 ostatnich dostarczeń. Każdy wpis zawiera:
| Pole | Opis |
|---|---|
| Event | Typ zdarzenia, które wywołało dostarczenie |
| Status | pending, in_progress, completed lub errored |
| Attempts | Liczba prób dostarczenia |
| Request headers | Nagłówki wysłane wraz z żądaniem |
| Response | Kod statusu HTTP lub komunikat błędu |
| Timestamp | 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 |
Przechowywanie danych
Logi dostarczania są przechowywane przez 30 dni, a następnie automatycznie usuwane. Aby zachować dane dłużej, należy zapisywać ł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ą | Zweryfikować podpis na podstawie surowej treści żądania z aktualnym kluczem |
| Przekroczenie limitu czasu dostarczenia | Endpoint potrzebuje więcej niż 15 sekund | Zwrócić 200 natychmiast i przetworzyć dane asynchronicznie |
| Webhook automatycznie wyłączony | 15 kolejnych niepowodzeń | Naprawić endpoint, a następnie kliknąć Resume |
| Adres URL odrzucony | Prywatny adres IP lub protokół HTTP | Użyć adresu HTTPS prowadzącego do publicznego adresu IP |
| Zdarzenia nie są wyzwalane | Webhook wstrzymany lub typ zdarzenia nie jest subskrybowany | Sprawdzić status webhooka i zasubskrybowane zdarzenia |
Szybka lista kontrolna
- Skopiować klucz podpisu ze strony szczegółowej webhooka
- Zaimplementować weryfikację podpisu HMAC-SHA256 w endpoincie
- Odrzucać żądania ze znacznikami czasu starszymi niż 5 minut
- Zwracać kod statusu
2xxw ciągu 15 sekund - Obsługiwać ponowne próby w sposób idempotentny (to samo zdarzenie może zostać dostarczone więcej niż raz)
- Monitorować logi dostarczania pod kątem błędów
- Skonfigurować alerty na wypadek automatycznego wyłączenia webhooka