Webhook Security
Shared Secret
| Complexity |
|
| Pros |
|
| Caveats |
|
| Examples |
|
In our research, 10% of the webhook providers use Shared Secrets — in the form of Basic Authentication, shared credentials, bearer tokens, or a verification token — for authentication. In this method, the webhook provider and listener share a common secret used exclusively to authenticate webhook requests:
On webhook requests, the provider sends a webhook notification containing the message plus a shared secret in a pre-defined header variable or the Authorization header using the Basic Auth format (
Authorization: Basic <"username:password" in base64>):// Compare secrets in constant time to avoid leaking them through response timing const safeEqual = (a, b) => { const bufA = Buffer.from(a || '', 'utf8') const bufB = Buffer.from(b || '', 'utf8') return bufA.length === bufB.length && crypto.timingSafeEqual(bufA, bufB) } app.post('/webhook', (req, res) => { // get authorization header (Basic <value>) const b64auth = (req.headers.authorization || '').split('Basic ')[1] || '' // Get login and password const [login, password] = Buffer.from(b64auth, 'base64').toString().split(':') // Verify login and password are present and correct if (login && password && safeEqual(login, process.env.WEBHOOK_LOGIN) && safeEqual(password, process.env.WEBHOOK_PW)) { // Webhook Authenticated // process and respond... res.json({ message: "Success" }) }else{ res.status(401).send('Authentication required.') } })The webhook listener validates the value in the request versus the shared secret. Only requests with the correct secret are processed.
Basic Authentication, or shared credentials, or verification token on webhook requests
This security method addresses only the webhook service authentication and does not implement any control on message integrity. Even with HTTPS, the shared secret is processed in clear text, increasing the risk of the secret getting compromised.
Therefore, their use should be avoided in production or used only with compensatory controls — such as IP Restrictions and callback requests — to mitigate risks. See Best Practices for Webhook Consumers.
Providers are moving away from shared secrets
Several providers that started with shared secrets have since added HMAC signatures:
- GitLab sends the configured secret in the
X-Gitlab-Tokenheader, but now says the secret token is "not recommended for new webhooks". Its signing tokens follow the Standard Webhooks specification, and both can be configured at once during migration. - Zoom replaced its plaintext verification token with HMAC-SHA256 signatures and a URL validation challenge — see Zoom.
- Slack sends a
tokenwith its URL verification handshake, but now marks it deprecated in favor of signing secrets.
Note
Some services offer basic auth as a quick option for development and unit testing, alongside more robust security controls for production usage. DocuSign, for example, offers basic authentication, Request Signatures with HMAC and Mutual TLS, and encourages the use of HMAC and mTLS in production use-cases.