Binding a Refresh Token to the Device

Part of the Refresh Token Design series. The Actual Defect The previous post ended on a reframing worth repeating. Reuse detection was never really about token ordering. It was trying to answer “is this a different person” by looking at “has this token been seen”, which is a bad proxy, and the false logouts are the evidence. The real defect is that a refresh token is a bearer secret. Whoever holds the bytes is the session. Copy them out of storage, a log, a crash report, a proxy, and you are indistinguishable from the person they belong to. ...

July 19, 2026 · 6 min · 1247 words · Sagar Nayak

Dropping Reuse Detection Gave Two People One Session

Part of the Refresh Token Design series. I Have Shipped the Other Answer Twice Two systems I have written and published about keep a table of spent refresh tokens and treat a repeat as an attack. One uses a used_refresh_tokens table and a queue in the client. The other hashes the token and rejects the second presentation outright. That is the standard advice and I still think it is defensible. This post is about what happens when you take it out, which the previous post in this series did, and what that actually costs once you look at the code rather than the intention. ...

July 12, 2026 · 6 min · 1157 words · Sagar Nayak

Three Scope Tiers for a Half Signed In Session

Part of the Refresh Token Design series. Signing In Is Not a Boolean Most auth code treats the session as a switch. Either somebody is in or they are not. Real sign-in has states in between, and each one needs a session that exists and reaches almost nothing. Somebody types a correct password and owes a second factor. They are not signed in, but they have to be able to call the route that lists their factors, the route that sends a code, and the route that verifies one. Those routes need to know who is answering, which means a session, which means a token. ...

July 5, 2026 · 6 min · 1222 words · Sagar Nayak

Refresh Token Rotation With a Previous Pair

Part of the Refresh Token Design series. The Problem With Single Use Single use refresh tokens are the standard advice and the advice is right. A refresh token that works twice is a refresh token somebody can steal and use behind you. The trouble is the failure mode when a response goes missing. A client sends its refresh token. The server rotates, writes the new pair, and answers. The answer never arrives, because the tunnel dropped, the phone changed cell, the laptop lid closed. The client still holds the old token, and the old token is now spent. It retries, gets refused, and the person is looking at a login screen because of one lost packet. ...

June 28, 2026 · 7 min · 1406 words · Sagar Nayak

Your JWT Was Never Stateless

What This is a nine part series on refresh token rotation, session records, and device binding, built around one claim: the JWT in your auth system is not a stateless assertion, and treating it as one is what makes the design complicated. A JWT is three useful properties. It expires on its own, it cannot be modified without invalidating the signature, and it can carry data you put there. That is a good envelope. It is not an authority on whether the person holding it should still be let in. ...

June 21, 2026 · 7 min · 1481 words · Sagar Nayak