Security
OTP Security Guide
Updated: 2026-02-22 - Added security guidance for custom OTP message templates
This guide covers the security controls and threat mitigations implemented in the OTP service.
Security Controls
Code Generation
- Cryptographically secure random generation using
System.Security.Cryptography.RandomNumberGenerator - No predictable patterns or sequential codes
- Configurable length (default 6 digits)
- Uniform distribution ensures all codes equally likely
Storage Security
- Only SHA-256 hashes stored - plaintext codes are never persisted
- Constant-time comparison prevents timing attack information leakage
- Automatic expiration and cleanup via Orleans timers
- Grain state encryption via Marten/PostgreSQL
Rate Limiting
- Distributed rate limiting via Redis-backed FusionCache
- Per-phone number limits: 3 requests per 10 minutes
- Per-tenant limits: 100 requests per 1 minute
- Sliding window algorithm prevents burst attacks
Transport Security
- SMS delivery only - no codes in API responses
- HTTPS/TLS for all API communications
- Tenant isolation enforced at grain level
- Request context validation ensures proper authorization
Message Template Safety
- Server-side placeholder expansion only (
{code},{minutes}) - No template execution/runtime evaluation beyond simple placeholder replacement
- Unknown placeholders remain literal text (not interpreted)
- Do not include secrets/PII in custom templates beyond the OTP code itself
Threat Mitigation
| Threat | Mitigation | Implementation |
|---|---|---|
| Brute Force | Rate limiting, max attempt limits | FusionCache distributed rate limiting with 3 attempts per phone |
| Timing Attacks | Constant-time code comparison | XOR-based comparison with no early exit |
| Code Interception | Short expiration, single-use | 10-minute expiration, one-time verification |
| Replay Attacks | One-time verification only | Status changes to Verified after first use |
| Pattern Guessing | Cryptographically secure RNG | RandomNumberGenerator.GetInt32() |
| Database Breach | Hash-only storage | SHA-256 hashes, no plaintext codes |
| Tenant Isolation | Grain-level tenant scoping | Directory grain keyed by tenant ID |
Architecture Security
Grain Isolation
Each tenant has isolated grains ensuring:
- No cross-tenant OTP access
- Per-tenant rate limiting
- Tenant-scoped audit logging
Code Verification Flow
Audit Trail
All OTP operations are logged with:
- Timestamp (UTC)
- OTP Request ID
- Tenant ID
- Phone number (hashed in logs)
- IP address of requester
- Operation type (generate, verify, cancel)
- Result (success, failure, expired)
Example log entry:
Code
Compliance
Data Retention
- OTP records: Retained for 90 days
- Audit logs: Retained for 1 year
- Rate limit counters: Expire after configured windows (phone: 10 minutes, tenant: 1 minute)
Privacy
- Phone numbers stored in E.164 format
- No personal data linked to OTPs
- Automatic cleanup of expired OTPs
- GDPR compliant deletion on request
Security Checklist
When implementing OTP in your application:
- Never display OTP codes in UI or logs
- Implement retry logic for verification failures
- Show remaining attempts to users
- Handle rate limit errors gracefully
- Implement timeout countdown UI
- Use HTTPS for all API calls
- Validate phone number format client-side
- Implement resend with rate limiting
- Log all OTP operations for audit
Incident Response
Suspected Compromise
- Cancel affected OTPs via API
- Review audit logs for suspicious patterns
- Adjust rate limits if needed
- Contact security team for investigation
Rate Limit Bypass
If legitimate users are rate limited:
- Check rate limit configuration
- Whitelist specific numbers if needed
- Increase tenant limits for high-volume users
- Monitor for abuse patterns
Best Practices
- Short expiration: 5-10 minutes maximum
- Limited attempts: 3 attempts maximum
- Secure delivery: SMS or push notification only
- No code storage: Never store codes client-side
- Clear UX: Show expiration time and remaining attempts
- Fallback options: Provide alternative verification methods
Penetration Testing
Recommended tests:
- Brute force verification - Should be rate limited
- Timing analysis - Should be constant time
- Cross-tenant access - Should be denied
- Expired OTP reuse - Should fail
- Max attempt bypass - Should be enforced
References
Last modified on