How I built a 7-layer security stack for a software licensing API
The Problem
If you build desktop software and sell it, you need a way to verify that the person running your app actually paid for it. The typical solution: license keys + an API that validates them.
But a simple "check key against database" endpoint gets cracked in hours. Replay attacks, shared keys, spoofed hardware IDs, brute-force attempts — the attack surface is massive.
I needed something better. So I built AuthVolt (https://authvolt.net) with 7 independent security layers that every API request must pass through.
The Architecture
Layer 1: Perimeter Firewall
Before any application code runs, incoming requests are checked against:
- Blocked IP addresses and CIDR ranges
- Country-level geo-blocking
- Banned user-agent patterns
This is pure filtering — no business logic, no database queries. Malicious traffic is dropped at the edge.
Layer 2: Adaptive Rate Limiting
Every action has its own rate limit bucket, keyed by IP + action_type.
Why per-action? Because a failed login attempt shouldn't block the same IP from registering. And a registration shouldn't affect API authentication requests.
Progressive throttling: first offenses get slowed down, repeat offenders get temporary bans.
Layer 3: Bot Detection
Automated scripts, headless browsers, and credential-stuffing tools are identified by behavioral patterns. Suspicious requests are challenged (CAPTCHA or math verification) before reaching any auth logic.
Layer 4: Deep Payload Inspection
Every request body is analyzed across 16+ attack categories:
- SQL injection patterns
- XSS payloads
- Path traversal attempts
- Deserialization exploits
- Command injection
- And more
This runs on every request, not just auth endpoints.
Layer 5: HWID Verification
License keys are bound to a cryptographic hardware fingerprint. The client app collects hardware identifiers (CPU, motherboard, disk serial, etc.), hashes them, and sends the HWID with every auth request.
If the HWID doesn't match what's registered — the key is rejected instantly. Shared keys become worthless.
Layer 6: Endpoint Hardening (Enterprise)
Enterprise-tier endpoints use:
- Custom URL paths (no standard
/api/authto discover) - Dynamic routing that changes on configuration
- Response encryption
Static analysis of the binary won't reveal the endpoint. Packet sniffing won't reveal the response format.
Layer 7: Continuous Monitoring
Every authentication event is logged with:
- Timestamp, IP, user-agent
- HWID fingerprint
- License key used
- Result (success/fail/blocked)
- Which security layer rejected it (if applicable)
Anomalous patterns trigger alerts. If one key suddenly authenticates from 50 different IPs — you know immediately.
Key Security Decisions
Anti-timing attacks on login:
// Even if user doesn't exist, run password_verify against a dummy hash
// This prevents timing-based username enumeration
if (!$user) {
password_verify($password, '$2y$12$dummy.hash.here');
return false;
}
Per-account lockout with sliding window:
Instead of permanent lockouts (which become a DoS vector), I use a 30-minute sliding window. 5 failed attempts in 30 minutes = temporary lock. Window resets naturally.
Constant-time token comparison:
All CSRF and session token comparisons use hash_equals() — never === or strcmp().
Results
- Auth latency: <50ms per request
- Zero framework dependencies (pure PHP 8 + MySQL)
- Runs on any standard hosting
- Full admin panel with 30+ management pages
The platform is live at https://authvolt.net with a free tier if you want to see it in action.
What security measures would you add? What do you think is overkill? I'd love to hear from developers who've dealt with similar problems.