Go
Проверка вебхуков
Проверьте подпись доставки, прежде чем доверять её содержимому.
Проверка доставки
package main import ( "io" "log" "net/http" "os" "github.com/bfzli/openemail-go") func main() { secret := os.Getenv("OPENEMAIL_WEBHOOK_SECRET") http.HandleFunc("/webhooks/openemail", func(writer http.ResponseWriter, request *http.Request) { payload, err := io.ReadAll(http.MaxBytesReader(writer, request.Body, 1<<20)) if err != nil { writer.WriteHeader(http.StatusBadRequest) return } event, err := openemail.VerifyWebhookSignature(payload, request.Header, secret) if err != nil { writer.WriteHeader(http.StatusBadRequest) return } log.Println(event.String("type"), event.ID()) writer.WriteHeader(http.StatusNoContent) }) log.Fatal(http.ListenAndServe(":8080", nil))}openemail.VerifyWebhookSignature читает заголовок X-OpenEmail-Signature, проверяет его HMAC по метке времени и телу за постоянное время и возвращает событие как openemail.Object. Секрет тот самый, который вернул client.Webhooks.Create.
Передавайте необработанное тело в точности таким, каким оно пришло. Тело, которое разобрали и закодировали заново, уже не совпадает со своей подписью.
Старые доставки
payload := []byte(`{"id":"evt_1","type":"email.received"}`)headers := http.Header{"X-OpenEmail-Signature": {"t=1767225600,v1=5f2d"}} _, err := openemail.VerifyWebhookSignature(payload, headers, "whsec_example", openemail.WithTolerance(time.Minute)) if errors.Is(err, openemail.ErrWebhookSignature) { fmt.Println("refused:", err)}Доставка старше пяти минут отклоняется, поэтому перехваченный запрос нельзя воспроизвести позже. openemail.WithTolerance меняет эти пять минут, а ноль принимает доставку любого возраста.
- Отсутствующий или неверно составленный заголовок, несовпадающая подпись и слишком старая доставка возвращают ошибку, которая совпадает с
openemail.ErrWebhookSignature. - После смены секрета доставка может нести больше одной подписи, и достаточно совпадения любой из них.
- Отвечайте статусом 2xx быстро. Доставка, получившая любой другой ответ, повторяется позже.