How I built a 7-layer security stack for a software licensing API

php dev.to

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/auth to 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;
}
Enter fullscreen mode Exit fullscreen mode

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.

Source: dev.to

arrow_back Back to Tutorials