Authentication
Each hook can require authentication. Three modes are available.
None (default)
[hooks.auth]
mode = "none"
No authentication required. Anyone who knows the URL can trigger the hook.
Bearer Token
[hooks.auth]
mode = "bearer"
token = "my-secret-token"
Callers must include the token in the Authorization header:
curl -X POST http://localhost:8080/hook/deploy \
-H "Authorization: Bearer my-secret-token"
The token can reference an environment variable:
[hooks.auth]
mode = "bearer"
token = "${{DEPLOY_TOKEN}}"
HMAC Signature
[hooks.auth]
mode = "hmac"
header = "X-Hub-Signature-256"
algorithm = "sha256"
secret = "${{WEBHOOK_SECRET}}"
The caller signs the request body with the shared secret. Sendword verifies the signature using constant-time comparison to prevent timing attacks.
This is the standard approach for GitHub, GitLab, and most webhook providers:
BODY='{"ref": "refs/heads/main"}'
SIG=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | cut -d' ' -f2)
curl -X POST http://localhost:8080/hook/github \
-H "X-Hub-Signature-256: sha256=$SIG" \
-H "Content-Type: application/json" \
-d "$BODY"
Failed authentication
Requests that fail authentication are logged as trigger attempts with an auth_failed status. They never reach the executor.