OTP is one layer of protection
A one-time code proves access to a delivery channel at a particular moment. It reduces password-reuse risk, but it does not stop every attack by itself.
An attacker may guess codes, trigger large send volumes, enumerate accounts through error text, steal an API key, or trick a user into sharing a code. Secure the full flow rather than only the six-digit generator.
Short expiration and one-time use
A standard Cascade code has 6 digits and expires after 300 seconds. Once verification succeeds, the same code must not be accepted again.
Define resend behavior explicitly: decide whether a new send invalidates the previous code. The interface should make this clear. Multiple active codes confuse users and support teams.
Limit send attempts
An IP-only limit is insufficient because legitimate users may share an address while attackers can rotate addresses. Combine limits by:
- phone number;
- account or session;
- IP address and subnet;
- API key or company;
- verification
purpose.
After a limit is exceeded, return a predictable 429 response and stop immediate automated retries. Display a countdown until resend becomes available.
Protect verification
A six-digit value has a finite search space, so verify must limit attempts. After repeated failures, add delay or invalidate the active challenge.
The phone and purpose must match the original send. Never accept a code by its numeric value alone without binding it to its recipient and intended action.
Complete login or a protected operation only after confirmed success: true from POST /api/otp/verify.
Keep the API key on the server
The Bearer token authorizes delivery and balance use. Do not embed it in browser JavaScript, mobile packages, or public repositories. Store it in a secret manager or backend environment variable.
Operational safeguards include separate test and production keys, restricted staff access, fast revocation, planned rotation, and redaction from errors and analytics.
If a key is compromised, revoke it first, issue a replacement, and inspect request history, balance changes, and unusual recipients.
Safe responses and logs
Messages such as “user not found” enable account enumeration. For recovery flows, return a neutral response explaining that instructions will be sent if the submitted data is eligible.
Useful logs contain a request ID, HTTP status, latency, channel, and technical result. They should not contain full OTP values, Bearer tokens, webhook secrets, or unnecessary personal data. Mask phone numbers while preserving enough context for support.
Monitoring signals
Alert on sharp increases in sends, repeated 422 or 429 responses, sudden balance consumption, and unfamiliar network patterns.
Monitor successful delivery and successful verification separately. High delivery with very low verification can indicate a UI defect, abuse, or mismatched purpose values.
Production checklist
- API calls originate from the backend only.
- Codes expire after 5 minutes and cannot be reused.
- Send and verify use multiple rate-limit dimensions.
- Resend has a cooldown.
- Codes are bound to phone and
purpose. - Logs redact secrets and OTP values.
- Responses do not disclose account existence.
- Alerts cover abnormal traffic and balance use.
- The team has an API-key revocation procedure.
- High-risk actions receive additional protection.
See API errors for response handling and the integration guide for the complete server flow.