123eworld Knowledge Hub → Transactional SMS → Page 151
Transactional SMS API Request Signing: HMAC, Canonical Requests, Replay Protection and Secure Verification
A technical reference for signed SMS API requests covering HMAC, canonicalization, timestamps, replay protection, raw request bodies and key rotation.
Why sign requests
API keys authenticate a caller, while request signing can add integrity and replay controls for sensitive integrations. A signature allows the server to verify that defined request data was created using a shared secret and has not been modified. The value is strongest when the platform defines exactly what is signed and provides reliable client libraries.
HMAC basics
HMAC produces a keyed digest over canonical request data. The server calculates the expected signature with the shared secret and compares it using a safe constant-time comparison. The cryptographic primitive should come from a well-maintained standard library rather than custom code.
Canonical representation
Both sides must sign exactly the same bytes. Define the HTTP method, normalized path, timestamp, body hash and required headers in a precise canonical format. Signature failures often come from JSON serialization, whitespace, URL encoding or header-order differences rather than from the HMAC algorithm itself.
Raw request body
If the signature includes the request body, verify the original byte representation before a framework parses and reserializes it. Two JSON documents can represent the same data while containing different bytes. Signing parsed-and-reformatted JSON can therefore create false signature failures.
Timestamp and replay
A captured valid request should not remain usable forever. Include a timestamp and enforce a short acceptance window. A nonce or unique request identifier can provide additional replay protection. Store enough recent identifiers to detect reuse without creating an unbounded database workload.
Key rotation
Use key versions so clients can introduce a new secret before the old one expires. During overlap, the server can accept both versions and record which one authenticated each request. Once adoption is confirmed, retire the old key.
Authentication order
Verify the signature before expensive business processing. A public endpoint should not parse complex templates, access large databases or call providers before the request is authenticated. This protects both performance and security.
Error handling
Return a deliberately generic authentication error. Do not tell an attacker whether the timestamp, key identifier or signature was the specific component that failed. Detailed diagnostics can be retained in protected security logs.
SDK support
Provide signing helpers in official SDKs when possible. Canonicalization is easy to implement inconsistently across programming languages. A small helper that produces the exact expected signature can eliminate an entire category of integration failures.
Testing
Test modified bodies, altered headers, expired timestamps, reused nonces, invalid signatures, key rotation and different JSON whitespace. Test large payloads and Unicode content because encoding assumptions can affect body hashing.
Performance
Signature verification should remain lightweight enough for high request volume. Keep the replay store efficient and avoid synchronously querying a slow external service for every signature. Rate-limit repeated invalid attempts to reduce abuse.
Common mistakes
Do not sign a representation that the server later changes before verification. Do not use a raw password hash as an improvised signature protocol. Do not accept an unlimited timestamp window. Do not compare signatures with ordinary string operations if the platform's security guidance requires constant-time comparison.
Developer takeaway
Request signing is only as reliable as its canonicalization contract. Document the exact fields and bytes that are signed, provide tested examples and make replay protection part of the protocol rather than an optional feature.
Implementation pattern
Define a canonical signing string containing method, path, timestamp, body hash and key version. Hash the exact raw request body and use a standard HMAC implementation. Verify timestamp and replay controls before business processing.
Failure example
If a framework reformats JSON before signature verification, the body hash can differ from the client calculation. Capture the original request bytes and verify them before parsing.
Production rule
Document the exact bytes and fields that are signed; naming the algorithm alone is not an integration specification.
Operational reference
Security review should include canonicalization, replay storage, key rotation, timestamp tolerance, failed-attempt rate limiting and logging. A signing scheme is not complete until its operational lifecycle is defined.
Canonicalization example
A practical canonical request might combine method, normalized path, timestamp, key ID and SHA-256 body digest separated by fixed newline characters. The exact format is a contract and should be identical in every SDK. Do not improvise optional whitespace or alternate JSON formatting rules.
Replay-store design
Replay detection can use a short-lived store keyed by tenant, key version and nonce or request identifier. The store needs bounded retention because replay windows are intentionally short. Rate-limit repeated invalid signatures so an attacker cannot turn verification into a high-volume storage workload.
Key compromise
If a signing secret is suspected to be exposed, revoke the affected key version and activate a replacement. Keep the old version's audit evidence so security teams can identify which requests were authenticated with it. Do not delete historical security records simply because the key is no longer valid.
Protocol documentation
Publish examples for at least one raw HTTP request, one canonical string and one computed signature. Developers should be able to reproduce the signature independently and compare intermediate values during integration testing.
Clock tolerance
Clock skew should be bounded rather than ignored. If the accepted timestamp window is too small, legitimate clients with inaccurate clocks will fail; if it is too large, replay protection becomes weaker. Document the tolerance and recommend time synchronization.
Replay versus duplicate
Replay protection prevents reuse of the same signed request, while idempotency prevents duplicate business operations. They solve different problems and should not be treated as substitutes.
Audit evidence
Record key version, authentication result, timestamp and request ID. This allows security teams to investigate suspicious patterns without storing the signed secret or full sensitive payload.
Final engineering rule
Use standard cryptography, precise canonicalization and bounded replay protection. Never invent a signing protocol ad hoc for production traffic.
Production reference
Production teams should monitor invalid-signature rates separately from ordinary authentication failures. A sudden spike can indicate a broken deployment, clock drift, key mismatch or an attack. The response should first determine which category changed before rotating every key.
Production reference
The replay store should be sized for the accepted request rate and timestamp window. A very short replay window reduces storage but can create false failures for slow clients; a very long window increases exposure. Select the window from actual integration behaviour and security requirements.
Production reference
Finally, keep signing tests as permanent interoperability tests. When SDKs or gateway frameworks change, run known request vectors to ensure canonicalization and signature output remain identical.
Design review
Request signing should be evaluated together with transport security, authentication and idempotency. TLS protects the network path, signing protects the defined request representation and idempotency protects the business operation from duplicate retries. Each control solves a different problem.
Reference checklist
Confirm canonical vectors, raw-body verification, timestamp validation, replay detection, key rotation, invalid-attempt controls and SDK interoperability.
Reference architecture note
A mature signing system should make interoperability testable before production. Provide fixed sample requests and expected signatures, document encoding precisely and publish test credentials that cannot access real messaging. This allows developers to solve canonicalization problems safely before connecting their application to production traffic. It also gives the platform a stable regression suite whenever gateway or SDK code changes.
Final production test
The final production test should use a known request vector, then deliberately modify one signed component. The platform must reject the modified request while continuing to accept the original vector. Repeat the test after key rotation to confirm both security and operational continuity.
Final reference rule
Keep cryptographic verification before business processing. Authentication should be a gate, not an afterthought performed after expensive application work.
Documentation rule
Document the signing protocol alongside the API version so changes to canonicalization are treated as contract changes. A working signature implementation is not enough; customers need stable examples and migration guidance.
Final check
Use fixed test vectors in every SDK release.
Continue through the 123eworld Knowledge Hub
Explore the complete 123eworld Knowledge Hub for practical SMS API, transactional messaging, queue, security and developer architecture guides.
Visit 123eworld.com for messaging and digital communication services.