Why interviewers keep asking if you can revoke a JWT

Updated · techinterview.org

The fastest way to tell a mid-level backend candidate from a senior one is to hand them a JWT and ask how they’d log the user out right now, before the token expires. The mid answer is “delete it from the client.” The senior answer opens with “you mostly can’t, and here’s what that costs you.” Almost everything interesting about auth interviews lives in that gap, so it pays to know exactly why the gap exists.

OAuth authorizes, OpenID Connect authenticates

The mistake interviewers set traps for is treating OAuth 2.0 as a login protocol. It isn’t. OAuth answers one question: is this application allowed to call this API on behalf of this user? That’s authorization. It tells you nothing reliable about who the user is. If you take an OAuth access token, see that it’s valid, and treat that as proof of identity, you’ve built the classic confused-deputy login bug where any app holding a token for your API can impersonate its owner.

OpenID Connect sits on top of OAuth and adds the missing piece: an id_token, a signed JWT carrying claims like sub (a stable user id), iss, aud, and exp. The access token is for the resource server; the id_token is for your client, so it can learn who just logged in. A candidate who says “access token goes to the API, id_token stays with the app, and I check signature, issuer, and audience before I trust a single claim” has already cleared a bar most people trip over. The follow-up is usually “what’s in an access token then?” and the correct answer is: whatever the authorization server put there, which might be a JWT or might be an opaque string you can’t read at all.

Why the implicit flow is gone and PKCE is everywhere

If you describe the old implicit flow, where the token comes back in the URL fragment, as your default, you’ve dated yourself. OAuth 2.1 folds a decade of security guidance into one spec: it drops implicit entirely, requires exact redirect-URI matching instead of prefix or wildcard, and mandates PKCE for every client, not just mobile apps.

PKCE exists because single-page apps and native apps have nowhere safe to keep a client secret. Anyone can crack open a mobile binary or read your JavaScript bundle. So instead of a static secret, the client generates a random code_verifier per request, sends the server its SHA-256 hash as the code_challenge, and later proves it holds the original verifier when it swaps the authorization code for tokens. An attacker who intercepts the code in a redirect can’t use it, because they never saw the verifier. Being able to walk through that exchange, and say why prefix matching on redirect URIs is a real open-redirect risk, reads as someone who has debugged this in production.

Access tokens, refresh tokens, and the five-minute rule

Access tokens should be short-lived. For anything touching sensitive data, five to fifteen minutes is normal. The reason is exactly the revocation problem below: a short life caps the blast radius of a leaked token without any extra machinery. Refresh tokens live much longer, days to weeks, and exist so the user doesn’t re-authenticate every ten minutes. The refresh token is the higher-value secret, and a good candidate treats it that way.

Refresh token rotation is where recent interviews have moved. RFC 9700, published as BCP 240 in January 2025, is worth naming: it says a refresh token issued to a public client must either be sender-constrained or rotated on every use. Rotation means each refresh returns a brand-new refresh token and invalidates the old one. The payoff is theft detection. If a rotated-away token ever gets presented again, the server knows something is wrong, because either the real client or an attacker is replaying a spent token, and the safe move is to revoke the whole token family and force a fresh login. Candidates who only describe rotation as “more secure” miss the actual mechanism, which is reuse detection.

The revocation problem, stated plainly

Here’s the tradeoff at the center of every JWT question. A self-contained JWT is validated by checking a signature, so your API needs no database round trip to trust it. That statelessness is the whole appeal, and it’s also why you can’t revoke one. The token stays valid until exp no matter what happens on your side, because your side isn’t consulted. Logout, a password change, an admin ban, a stolen laptop: none of them reach a token already in the wild.

There are three answers that hold up, and the right one depends on the threat you’re defending against. The first is to lean on short expiry and simply accept the window; if access tokens die in five minutes, a revoked user is locked out within five minutes, which is fine for most apps. The second is a denylist: store revoked token IDs (the jti claim) in something fast like Redis, with each entry’s TTL set to the token’s remaining lifetime so the list stays small and self-cleaning. That reintroduces a lookup, but only for the tokens you’ve actually killed. The third is versioning: keep a token_version per user, embed it in the token, bump it on logout or password change, and reject any token whose version is stale. That’s one cheap comparison, usually against a value you’re already loading with the user.

And if the interviewer keeps pushing on “but I need instant, guaranteed revocation,” the correct answer is that you’ve argued your way back to stateful tokens. Opaque tokens plus token introspection (RFC 7662), where the API asks the authorization server whether a token is still good, give you a real kill switch at the cost of a lookup on the hot path. There’s no free lunch here, and naming the tradeoff out loud is the point of the question.

Token type What it’s for Instantly revocable? Validated by Typical lifetime
Access token (JWT) Calling the resource API No, only via denylist or version check Local signature check, no DB 5-15 minutes
Access token (opaque) Calling the resource API Yes Introspection call to auth server 5-60 minutes
Refresh token Getting new access tokens Yes, server-side store Lookup plus rotation/reuse check Days to weeks
ID token (OIDC) Telling the client who logged in Not applicable, never sent to APIs Signature, issuer, audience, nonce Minutes, single use
Session cookie Server-rendered app sessions Yes, delete the server-side session Session store lookup Hours to days

Making a stolen token useless: DPoP and mTLS

A standard bearer token is like cash. Whoever holds it can spend it, which means a token pulled from a log file, a compromised proxy, or a leaky browser extension works fine for the thief. The 2026 senior answer to “how do you limit the damage of a leaked token” is sender-constrained tokens.

DPoP (RFC 9449) binds a token to a key pair the client generates and never shares. On every request the client attaches a short signed proof showing it holds the private key that matches the public key baked into the token. Steal the token without the key and it’s inert. Mutual TLS gives you the same property by binding the token to a client certificate, which suits service-to-service traffic where you already run certs. You don’t need to have shipped DPoP to score here; recognizing that PKCE protects the authorization code, rotation protects the refresh token, and DPoP protects the access token, three different leaks with three different defenses, is what separates a memorized answer from an understood one.

What actually gets asked

The questions cluster, and once you’ve seen the pattern they stop being surprising. A few phrased the way interviewers actually say them:

  • “Walk me through what happens between clicking Login with Google and landing back on our site.”
  • “A user reports their account was accessed after they changed their password. How is that possible with JWTs, and how would you prevent it?”
  • “Where do you store the access token in a single-page app, and what breaks with each choice?”
  • “Our mobile app and web app share an API. Same auth setup for both, or not?”
  • “An attacker got a copy of a valid access token. What can they do, and for how long?”

The token storage one catches people. localStorage is readable by any script, so an XSS bug hands over the token; an httpOnly cookie survives XSS but opens a CSRF surface you now have to close with SameSite and an anti-forgery token. There’s no clean winner, and the interviewer wants to hear you weigh XSS against CSRF rather than recite a rule you read once.

The tells that sink an otherwise good answer

Two mistakes end auth interviews early. One is claiming a JWT can be revoked as if statelessness were free; you can revoke, but only by adding back the state the JWT was supposed to remove, and pretending otherwise signals you’ve never run this in production. The other is storing anything sensitive in a JWT and forgetting it’s signed, not encrypted. Base64 is not encryption. Anyone can paste the token into a decoder and read every claim, so a token carrying a user’s email, role, and internal account flags is leaking all of it to whoever holds it. If the data must stay private, you want an encrypted token (JWE) or an opaque reference the client can’t read at all.

Get comfortable saying “it depends, and here’s the tradeoff” on these, because auth is one of the few areas where that phrase is the correct answer rather than a dodge. The person across the table has usually been burned by a token bug themselves, and what they’re really checking is whether you’d catch it before they get paged at 3am.

newsletter

What's actually being asked right now

Interview patterns & comp trends, straight to your inbox.

No spam. Unsubscribe anytime.

newsletter

What's actually being asked right now

Interview patterns & comp trends, straight to your inbox.

No spam. Unsubscribe anytime.

1972 Soviet postage stamp commemorating the Mars 2 probe

worth a read

Mars For The Rest of Us — a weekly-or-more deep dive on the technical side of Mars exploration: rocket propulsion, microbiology, mission architecture, and everything in between. Written by Maciej Ceglowski.

Read it on Substack
Scroll to Top