Chapter 13: Threat Modeling OpenID Systems — Thinking Like the Adversary

This is Part 13 of a chapter-by-chapter walkthrough of my book OpenID: Modern Identity for Developers and Architects. In the previous chapter we covered user lifecycle. Chapter 13 opens Part V — Security Engineering — by flipping perspective: from "how does this work" to "how does this break."


13.1 — Token Theft: The Ways They Actually Get Stolen

An access token or ID token in an attacker's hand is user impersonation. The theft vectors are well-known and keep working: XSS that reads tokens from browser storage, network interception where tokens somehow end up in URLs or plaintext HTTP, server-side leaks through logs and error pages, compromised endpoints that see tokens they shouldn't. Chapter 13 walks through each.

The defensive posture is defense in depth: HTTPS with strong TLS everywhere, tokens in Authorization headers only (never URLs), strict CSP, HttpOnly cookies where cookies are used, aggressive log hygiene, and — at the top end — token binding via DPoP or mTLS so a stolen token without the corresponding key is worthless.

13.2 — Replay Attacks and the nonce

A replay attack resubmits a captured valid message at a later time. OIDC's primary replay target is the authorization code (defended by one-time-use at redemption) and the ID token itself. The nonce parameter is what binds a received ID token to a specific authorization request your application made — without it, a token captured from one session could be replayed into another.

Generate nonces from a cryptographically strong source, store them in session state, and verify the returned ID token's nonce claim exactly matches. Skipping this because "we're using Authorization Code flow" is a common shortcut that turns into a CVE in the right circumstances.

13.3 — CSRF and the state Parameter

If an attacker can trigger your application to begin an OIDC flow on behalf of a user, they can potentially inject their own authorization response and get the victim's session tied to the attacker's account. Or worse.

The state parameter exists specifically to prevent this: it's the anti-CSRF token for the OIDC redirect. Generate it per-request, tie it to the user's session, and reject any callback whose state doesn't match the one you issued. Chapter 13 walks through the common ways teams weaken this: reusing state, comparing case-insensitively, not expiring state values.

Important: If your login-initiation endpoint can be triggered by a simple GET from an attacker-controlled page, and your state handling has any weakness, you probably have an account-takeover bug right now. This is the most common advanced OIDC vulnerability I've seen in real systems.

13.4 — Redirect Abuse and Mix-Up Attacks

Open redirects are the classic: an attacker manipulates your application's redirect URI to send the user (and the authorization code) somewhere they control. The spec's answer is strict exact-match redirect URI validation, which is why wildcards keep trying to sneak back in and why they keep getting rejected.

Mix-up attacks are the subtle cousin. If your application supports multiple identity providers and doesn't track which provider this specific flow was supposed to use, an attacker who controls one IdP can trick it into injecting responses as if they came from a different IdP. The fix: always validate iss against the expected provider for the flow, not just "any known provider."


What Chapter 13 Sets Up

After Chapter 13 you should be able to enumerate the major threats against your OIDC deployment, map each to the specific control that mitigates it, and audit your own code against this list. Security isn't a feature; it's a property of how carefully each of these pieces is wired.


Next up — Chapter 14: Hardening Your Identity Stack. Threats identified; now we set defaults. Redirect URI rules done right, aud validation and the confused deputy problem, token lifetimes that balance security and UX, and the specific disciplines around refresh token binding, rotation, and revocation.

Want the full picture? Grab OpenID: Modern Identity for Developers and Architects here for the complete threat catalog, real-world attack case studies, and the rest of the 22-chapter journey through modern identity.
2026-03-19

Sho Shimoda

I share and organize what I’ve learned and experienced.