Jak działa weryfikacja podpisu webhooka
Podpis webhooka to krótki dowód na to, że zdarzenie pochodzi od operatora płatności, a nie z przypadkowego żądania POST. Operator podpisuje treść żądania wspólnym sekretem lub kluczem prywatnym, a Twoja aplikacja weryfikuje podpis, zanim zaufa zdarzeniu. Jeśli zastanawiasz się, jak zweryfikować podpis webhooka, zacznij od sprawdzenia, czy podpis odpowiada dokładnie tej treści i kluczowi, których używa operator. Jeśli weryfikacja się nie powiedzie, najbezpieczniej zwrócić kod 401 lub 400 i nie aktualizować zamówienia.
Brzmi prosto. W praktyce rzadko takie jest.
Weryfikacja podpisu chroni przed fałszywymi fakturami, fikcyjnymi zwrotami i zmodyfikowanymi danymi, które na pierwszy rzut oka wyglądają wiarygodnie. Webhook informujący o „zakończonej płatności” jest bezużyteczny, jeśli każdy może go podrobić. W przypadku zespołów korzystających z poradnika dotyczącego bramki płatności kryptowalutowych dla e-commerce weryfikacja ta znajduje się między przyjęciem płatności a realizacją zamówienia. Dlatego jedno błędne założenie może zatrzymać cały proces.
Większość operatorów podpisuje całe surowe żądanie, znacznik czasu albo oba te elementy. Niektórzy używają HMAC-SHA256, inni nagłówka z wersją i kilkoma wartościami podpisu. Wystarczy jedna niezgodność. Operator może mieć rację, a Twoja aplikacja i tak odrzuci zdarzenie, jeśli zmienisz choćby jeden bajt.
Najpierw upewnij się, że problem rzeczywiście dotyczy podpisu
Logi powinny pozwolić ustalić to w mniej niż 5 minut. Jeśli tak się nie dzieje, nie zawierają wystarczająco szczegółowych informacji.
Zacznij od dokładnego kodu odpowiedzi i treści błędu. Odpowiedź 400 z komunikatem „nieprawidłowy podpis” wskazuje na coś innego niż błąd 500 lub przekroczenie limitu czasu. Nieudane dostarczenie, błędne ścieżki, błędy TLS i przekroczenia limitu czasu na serwerze proxy mogą w panelu wyglądać na problemy z webhookiem, ale to różne kwestie. Jeśli operator pokazuje status „dostarczono”, a Twój endpoint zwraca 200, weryfikacja podpisu prawdopodobnie nie jest przyczyną problemu.
Sprawdź jednocześnie trzy rzeczy: dziennik dostarczeń operatora, dziennik aplikacji oraz dziennik odwrotnego serwera proxy, jeśli go używasz. Żądanie, które nigdy nie dociera do Twojego kodu, nie może nie przejść weryfikacji podpisu. Żądanie, które dociera do kodu, ale kończy się odpowiedzią 401, najpewniej może. Ważny szczegół: jeśli zdarzenie pojawia się w logach, ale nie ma błędu podpisu, kod może odrzucać dane dopiero później, już po weryfikacji.
Krótko mówiąc: zanim zmienisz kod, upewnij się, że dobrze rozpoznajesz objawy. Jeśli szukasz rozwiązania problemu „błąd weryfikacji podpisu webhooka jak naprawić”, najpierw ustal, na którym etapie żądanie zostaje odrzucone.
Sprawdź wspólny sekret lub klucz podpisujący
To najczęstszy błąd, a jego banalność potrafi uśpić czujność. Sekret webhooka w aplikacji musi dokładnie odpowiadać aktualnemu sekretowi w panelu płatności — także pod względem ukrytych spacji wklejonych z pola tekstowego. Jeśli operator zmienił sekret w zeszły wtorek, stary klucz nadal będzie w zmiennych środowiskowych, dopóki ktoś go nie zaktualizuje.
Porównaj sekret z panelu z tym ustawionym w środowisku wdrożeniowym, a nie tylko na swoim komputerze. Produkcja, środowisko testowe i środowisko lokalne powinny mieć osobne wartości. Zespół, który skopiuje testowy sekret do produkcji, może przez 2 godziny szukać przyczyny błędu weryfikacji podpisu, choć winny jest jeden wklejony ciąg znaków. Takie problemy często pojawiają się podczas uruchamiania usługi i migracji do innego operatora. Zespoły korzystające z poradnika dotyczącego bramki płatności kryptowalutowych dla e-commerce często zauważają niezgodność sekretów tuż po wdrożeniu nowej wersji procesu płatności.
Zachowuj stare klucze tylko wtedy, gdy operator obsługuje ich rotację z okresem nakładania się ważności. Jeśli przez krótki czas działają zarówno stary, jak i nowy klucz, weryfikator powinien najpierw sprawdzić aktywny klucz, a potem poprzedni. Jeśli operator nie obsługuje takiego rozwiązania, usuń stary klucz ze wszystkich środowisk. Nie zgaduj.
Odtwórz surową treść żądania dokładnie tak, jak została odebrana
Właśnie na tym etapie zawodzi wiele dobrych implementacji. Weryfikacja podpisu zwykle zależy od dokładnych bajtów surowej treści żądania webhooka wysłanej przez operatora, a nie od obiektu JSON, który framework utworzył po sparsowaniu danych. Jeśli kod zmienia liczby, przestawia pola, usuwa białe znaki lub normalizuje znaki końca wiersza, obliczony podpis może się różnić, nawet jeśli treść „wygląda” identycznie.
Niektóre frameworki odczytują treść tylko raz, a potem odrzucają oryginalny strumień. Inne automatycznie parsują JSON, zanim uruchomi się oprogramowanie pośredniczące. W rezultacie weryfikator otrzymuje odtworzony obiekt, a nie surową treść. Zwykle wystarczy najpierw zachować niezmieniony payload, a potem przekazać dokładnie ten sam bufor do funkcji weryfikującej podpis. Jedno ustawienie frameworka może zdecydować, czy treść zostanie zachowana, czy przekształcona.
Przykładowo payload z 14 polami może dotrzeć w określonej kolejności bajtów, której Twój kod nigdy nie zobaczy, jeśli parser sortuje klucze. Końcowy znak nowej linii może mieć znaczenie. Podobnie pojedyncza konwersja UTF-8. Tak — jeden niewidoczny znak potrafi zepsuć całą weryfikację.
Jeśli Twój stos technologiczny na to pozwala, przed parsowaniem zapisuj długość treści oraz skrót surowego żądania. Nie zapisuj sekretów. Zapisuj natomiast dokładną ścieżkę kodu, która odczytuje strumień. Dzięki temu łatwiej ustalisz, dlaczego test płatności kryptowalutowej czasem przechodzi w Postmanie, ale nie działa przy prawdziwym webhooku od operatora.
Zweryfikuj znacznik czasu, synchronizację zegara i ochronę przed powtórzeniami
Wiele mechanizmów webhooków uwzględnia znacznik czasu, aby nie dało się ponownie wysłać starych zdarzeń. Weryfikator może odrzucić żądanie, jeśli znacznik wykracza poza dopuszczalny przedział — często wynoszący 5 minut lub inny limit określony przez operatora. Chroni to przed atakami polegającymi na ponownym odtwarzaniu żądań, ale oznacza też, że zegar serwera musi wskazywać prawidłowy czas.
Sprawdź zegar systemowy na każdym serwerze obsługującym webhooki. Jeśli zegar spieszy się lub spóźnia o 3 minuty, podpis może nie przejść weryfikacji, mimo że payload jest prawidłowy. Jeśli serwer działa w kontenerze, sprawdź również czas hosta. Na maszynie podejmującej decyzję o weryfikacji powinna działać usługa NTP lub inna usługa synchronizacji czasu. Serwer, którego zegar różni się o 10 minut, może błędnie odrzucić prawidłowy webhook.
Ważna jest również ochrona przed powtórzeniami. Jeśli Twój kod zapamiętuje już użyte podpisy lub identyfikatory zdarzeń, upewnij się, że czas przechowywania w pamięci podręcznej odpowiada oczekiwanemu przez operatora oknu ponownych prób. Nieaktualny wpis w pamięci podręcznej może spowodować odrzucenie prawidłowego, ponownie dostarczonego zdarzenia. Ponowienie próby przez operatora to nie to samo co złośliwe ponowne odtworzenie żądania, więc kod powinien rozróżniać te sytuacje. To drobny szczegół o poważnych konsekwencjach.
Upewnij się, że nagłówek podpisu jest prawidłowo odczytywany
Nagłówki podpisu nie zawsze mają ten sam format. Niektórzy operatorzy wysyłają jeden nagłówek z pojedynczym skrótem, inni — listę par klucz-wartość oddzielonych przecinkami, etykietę wersji i znacznik czasu. Parser musi obsługiwać dokładnie taki format, jaki stosuje operator. Jeśli oczekuje v1=, a operator wysyła t= oraz kilka wersji, weryfikacja nie powiedzie się, zanim w ogóle rozpocznie się sprawdzanie kryptograficzne.
Zwróć uwagę na błędy związane z przycinaniem białych znaków. Spacje na początku i na końcu mają znaczenie. Podobnie błędy kodowania, gdy framework dekoduje nagłówki jako Latin-1 zamiast UTF-8. Zbędny znak nowej linii wklejony do zmiennej środowiskowej może spowodować niezgodność. Nie normalizuj nagłówka, chyba że operator na to pozwala. Nie zamieniaj wartości na małe litery, jeśli musi być bezpieczna dla danych binarnych. Te dwa błędy przysparzają więcej kłopotów, niż powinny.
Obsługa wielu schematów też wymaga ostrożności. Niektórzy operatorzy w okresie przejściowym udostępniają bieżący i poprzedni podpis. Weryfikator powinien wiedzieć, której wersji używa, i prawidłowo odrzucać nieznane wersje. Jeśli nagłówek zawiera zarówno znacznik czasu, jak i podpis, zweryfikuj oba. Jeśli dokumentacja operatora określa prefiks używany do podpisywania, zastosuj go dokładnie w opisany sposób. Więcej informacji o bezpiecznej obsłudze webhooków znajdziesz w artykule najlepsze praktyki w zakresie bezpieczeństwa płatności kryptowalutowych.
Przetestuj znany, prawidłowy webhook
Znane, prawidłowe zdarzenie pozwala zaoszczędzić czas. Wyślij je ponownie z panelu operatora albo skorzystaj z udokumentowanego przykładowego payloadu i porównaj oczekiwany podpis z tym obliczonym przez Twój kod. Jeśli przykład przechodzi weryfikację, ale zdarzenia z rzeczywistego ruchu nie, problem prawdopodobnie dotyczy konfiguracji, środowiska lub rotacji sekretu. Jeśli nie przechodzi żadne z nich, błąd leży w ścieżce wykonywania kodu.
Użyj jednego identyfikatora zdarzenia i jednego znacznika czasu. Następnie porównaj cztery elementy: surową treść, wartość nagłówka, sekret i zegar. To wystarczy, aby zlokalizować większość problemów. Payload testowy skopiowany do lokalnego pliku może zawierać formatowanie, którego prawdziwy endpoint nigdy nie otrzymuje, dlatego jeśli operator udostępnia narzędzie do ponownego wysyłania zdarzeń, zawsze z niego korzystaj. Jedno ponowne wysłanie jest lepsze niż 20 prób opartych na zgadywaniu.
Jeśli operator udostępnia kalkulator podpisów, sprawdź w nim ten sam payload. Jeśli wynik różni się choćby o jeden znak, problem dotyczy parsowania lub zachowania surowej treści. Jeśli wyniki są zgodne, ale operator nadal odrzuca żądanie, błąd dotyczy sekretu lub parsowania nagłówka. To rozróżnienie podpowiada, gdzie szukać dalej.
To także dobry moment, by wyraźnie oddzielić środowisko testowe od produkcyjnego. Zdarzenie testowe wysłane z użyciem sekretu produkcyjnego za każdym razem zakończy się błędem. Dopóki nie sprawdzisz etykiety środowiska, może to wyglądać identycznie jak problem z podpisem.
Zabezpiecz endpoint webhooka i monitoruj jego działanie
Gdy weryfikacja podpisu już działa, zadbaj o to, by tak pozostało. Zapisuj identyfikator zdarzenia, wynik weryfikacji, nazwę operatora i środowisko. Nie zapisuj całego sekretu. Nie zapisuj też pełnej surowej treści, jeśli zawiera wrażliwe dane klientów. Operatorom pokazuj krótki, czytelny komunikat o błędzie, a operatorowi płatności zwracaj prostą odpowiedź odrzucającą żądanie.
Regularnie zmieniaj sekret webhooka i dokumentuj cały proces. Bezpieczniejsza jest rotacja w 2 krokach: dodaj nowy klucz, sprawdź, czy oba klucze działają, jeśli operator obsługuje nakładanie się ich ważności, a następnie usuń stary. Oddziel endpointy testowe od produkcyjnych, aby pomyłka w środowisku testowym nie wpłynęła na aktywne zamówienia. To brzmi oczywiście, ale zespoły nadal mylą te środowiska.
Wysyłaj alerty, gdy pojawi się seria błędów weryfikacji podpisu, a nie po pojedynczym nieudanym podejściu. Jedna nieudana próba może być skutkiem błędnego ponowienia. Pięć błędów w ciągu 1 minuty wymaga uwagi. W alercie uwzględnij ścieżkę, operatora i kod odpowiedzi, aby osoba pełniąca dyżur mogła ustalić, czy problem dotyczy niezgodnego sekretu, błędu parsera czy zegara. Jeśli dopiero konfigurujesz endpoint, artykuł jak skonfigurować płatności kryptowalutowe pomoże Ci od początku zachować prostą ścieżkę obsługi webhooków.
Na koniec przygotuj krótką instrukcję zawierającą dokładne kroki naprawy błędu weryfikacji podpisu webhooka płatności kryptowalutowej. Uwzględnij w niej miejsce przechowywania sekretu, sposób ponownego wysłania zdarzenia oraz wpis w logach potwierdzający poprawną weryfikację. Instrukcja licząca 10 wierszy może oszczędzić godzinę pracy o 2 w nocy.




Comments