A webhook endpoint receives information that can trigger important work: updating an account, starting a deployment, or recording a change from another service. Receiving a request at the expected URL does not establish that the request came from the expected sender.
Signature verification adds that missing check. It should happen before the application trusts the payload enough to perform business actions.
Establish what is being verified
GitHub documents a shared-secret process for webhook verification. It sends a signature in the X-Hub-Signature-256 header, and the receiving application checks that signature against one calculated using its secret and the received payload.
GitHub recommends performing this validation before processing the delivery further. It also advises secure storage of the secret and warns against hardcoding it or committing it to a repository.
The signature is therefore part of the trust decision, not an optional logging field.
A request that merely claims to represent a familiar event should not be treated as authenticated.
Preserve the body required by the provider
Signature checks are sensitive to the data used in the calculation. Stripe’s documentation requires the raw request body, the signature header, and the secret associated with the endpoint.
Its guidance specifically warns about middleware that parses the body before the verification step. In an Express application, for example, middleware order can determine whether the original body remains available.
A JSON object can preserve the apparent meaning of a request while losing its original byte representation. Parsing and then serializing the object is not a reliable substitute for preserving the body required by the verification procedure.
Use the provider’s supported verification library and framework instructions wherever possible.
Test rejection as carefully as acceptance
A successful test delivery proves only part of the integration. The receiver should also reject a modified payload, an incorrect signature, and a request without the required authentication material.
Create a controlled test set using nonproduction data. Confirm that failed verification prevents downstream changes.
For example, a deployment integration should not create a deployment job merely because the JSON includes a recognized repository name. The authentication step must succeed before that event is allowed to influence the system.
Keep test configuration clearly separated from production configuration. A valid signature under the wrong test arrangement does not establish that the production endpoint is configured correctly.
Use the documented comparison and handling rules
GitHub advises using a constant-time comparison method rather than an ordinary equality comparison when implementing its signature check.
Different providers can use different headers, signing inputs, and validation procedures. Avoid copying one provider’s implementation and changing only the endpoint name.
After verification, validate that the event type and relevant identifiers are appropriate for the action being requested. An authenticated delivery still needs normal application-level checks.
Record enough operational information to investigate failures without turning logs into a collection of secrets or unnecessary payload data. A delivery identifier, verification outcome, and internal error category can be more useful than an indiscriminate request dump.
For a startup, a small webhook receiver can become a powerful entry point into production workflows. Treating authentication as the first processing step makes that integration easier to reason about, test, and maintain.
