HTTP service that accepts signed webhooks to record financial transactions with HMAC SHA256 validation and replay attack prevention.
# Build and start the service (database + server)
make up
# In another terminal, send a webhook
TIMESTAMP=$(date +%s)
NONCE=$(uuidgen)
BODY='{"user":"alice","asset":"BTC","amount":"1.5"}'
SECRET="default-secret-key"
MESSAGE=$(printf '%s\n%s\n%s' "$TIMESTAMP" "$NONCE" "$BODY")
SIGNATURE=$(printf '%s' "$MESSAGE" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}')
curl -i -X POST http://localhost:8080/webhook \
-H "Content-Type: application/json" \
-H "X-Timestamp: $TIMESTAMP" \
-H "X-Nonce: $NONCE" \
-H "X-Signature: $SIGNATURE" \
-d "$BODY"
# Check the balance
curl http://localhost:8080/balance/alice
# Collect metrics
curl http://localhost:8080/metrics
# Stop the service (Ctrl+C)
# Clean up (stop containers and remove volumes)
make down
# Run tests
make test
# Run linter
make lintPostgreSQL is accessible at localhost:5432 for use with SQL clients like Beekeeper Studio, DBeaver, pgAdmin.
URL: user:password@localhost:5432/signed_webhooks
The service prevents replay attacks using two mechanisms:
- Timestamp validation: Requests older than 5 minutes (configurable) are rejected
- Nonce uniqueness: Each nonce is stored in a separate
noncestable with a unique constraint
Attack scenario: Attacker captures and replays POST /webhook with nonce "abc123"
Validation steps:
- Is timestamp within tolerance (5 min)?
- Is signature valid?
- Is nonce unique?
Nonce uniqueness is enforced by Postgres's primary key constraint, leveraging ACID properties (Consistency, Isolation) to ensure each nonce is accepted only once, even under concurrent requests.
The nonce check and transaction insertion happen atomically. If the nonce was already claimed, the entire transaction rolls back.
See: ACID, Saga and Transactional Outbox
| Breno Baptista |
This project is licensed under the MIT License