STRIDE Threat Modeling for Web APIs
A structured approach to thinking about what can go wrong — before it does. Walking through STRIDE on a realistic streaming API.
Threat modeling sounds like an enterprise process with whiteboards and consultants. It doesn't have to be. STRIDE is a checklist — six threat categories you run through for each component or flow in your system. The output is a list of threats and mitigations, not a 40-page report.
STRIDE stands for: Spoofing, Tampering, Repudiation, Information Disclosure, Denial of Service, Elevation of Privilege.
Let's walk through a concrete example: a streaming API that issues encrypted stream tokens and proxies video embeds. This maps directly to what NodWatch's streaming pipeline does.
The System
Client → POST /api/stream/token (auth required)
→ GET /api/stream/proxy?token=... (validates + proxies embed)
The token encodes: embed URL, user ID, expiry (60 seconds), and the stream server selection.
S — Spoofing
Can an attacker impersonate a legitimate user or service?
Threat: An attacker replays a stolen stream token to access content without authentication.
Mitigation: Token expiry (60 seconds) limits the window. The token encodes the userId — the proxy route validates that the requesting session matches. Use AES-GCM encryption for tokens (not just base64) so the contents can't be modified or inspected.
Threat: An attacker spoofs the Origin header to bypass CORS restrictions on the token endpoint.
Mitigation: The token endpoint requires a valid authenticated session, not just an origin check. CORS is defense-in-depth; auth is the real gate.
T — Tampering
Can an attacker modify data in transit or at rest?
Threat: An attacker modifies the token query parameter to change the embed URL to one that serves malicious content in the iframe.
Mitigation: The token is AES-GCM encrypted with an authenticated tag. Any modification to the ciphertext renders the MAC invalid and the decryption fails. The embed URL is never taken from the URL — only from the decrypted, verified token.
Threat: The embed URL itself could be manipulated if the stream provider is compromised.
Mitigation: The frame-src CSP header only allows the five known stream provider domains. An injected URL from an unknown domain is blocked by the browser.
R — Repudiation
Can an attacker deny having performed an action?
Threat: A user disputes charges or accesses, claiming they never streamed certain content.
Mitigation: Log token issuance with user ID, timestamp, content ID, and IP. Log every proxy request with the same data. The token itself is signed with the user ID — it cannot be forged by another user.
I — Information Disclosure
Can an attacker access data they shouldn't?
Threat: The embed URL (which may contain partner API keys as query parameters) is exposed in client-side JavaScript or network logs.
Mitigation: The proxy route decrypts the token server-side and makes the outbound request from the server — the actual embed URL is never sent to the browser. The client only ever sees the proxy URL.
Threat: Error responses from the stream provider reveal internal implementation details.
Mitigation: The proxy catches all errors and returns a generic 503 to the client. Provider errors are logged server-side only.
D — Denial of Service
Can an attacker degrade or disable the service?
Threat: An attacker hammers POST /api/stream/token to exhaust server resources or trigger provider rate limits.
Mitigation: Rate limit token issuance per user (10/minute). The 60-second token expiry means tokens can't be stockpiled. Auth requirement means unauthenticated DoS is harder.
Threat: Large numbers of proxy connections exhaust connection pool capacity.
Mitigation: The proxy is deployed on Cloudflare Workers (auto-scaling). Timeouts on the outbound fetch prevent hanging connections.
E — Elevation of Privilege
Can an attacker gain capabilities beyond what they're authorized for?
Threat: A free-tier user obtains a stream token intended for premium content.
Mitigation: The token issuance endpoint checks the user's subscription tier before issuing a token for premium content. The token doesn't carry the tier — the check is at issuance time.
Threat: An attacker exploits a vulnerability in the token encryption to forge tokens without authentication.
Mitigation: Use crypto.subtle.importKey with AES-GCM-256. The 256-bit key is stored as a Cloudflare secret — not in source code or .env.
Running STRIDE takes 30–60 minutes for a well-defined flow. Do it for every new endpoint that handles auth, payments, or content gating. The output — a table of threats and mitigations — becomes the security section of your design doc.