Back to Blog
On this page2 sections

// tutorial

API token bugs that show up in everyday testing

qa.codesqa.codes · 13 June 2026 · 8 min read
IntermediateQA EngineersAPI testers
security-testingapi-testingtokensauth

You don't need a security team to find token bugs — most of them surface in ordinary API testing if you look at the token instead of past it. Here are the ones I hit regularly and how to test for them.

Auth tokens — bearer tokens, JWTs, API keys — are the thing every authenticated request carries and almost no one tests directly. The token is treated as a magic string that either works or doesn't, and testing stops at "I can log in." But the token itself is an input, and like any input it has failure modes: it can outlive its welcome, survive logout, work where it shouldn't, or leak where it can be stolen. These are findable in everyday API testing, no pentest required. They sit right alongside the auth bugs QA can catch.

The token bugs you'll actually find

The token outlives its expiry. Tokens are supposed to expire. Grab one, wait past its lifetime, and reuse it — does the server reject it? A token that works forever is a session-expiry bug wearing a different hat: anyone who captures it has permanent access.

Logout doesn't invalidate it. Log in, capture the token, log out, then replay the old token against an authenticated endpoint. If it still works, "logout" only cleared the client — the token is still valid server-side. This is one of the most common and most surprising findings.

A token works for the wrong scope or user. A token issued for a read-only scope succeeds on a write endpoint; a token for user A returns user B's data. The server is trusting the token's presence instead of checking its permissions — straight into authorization testing and IDOR territory.

The token leaks somewhere visible. Tokens in URLs (they end up in logs, history, and referrer headers), in error messages, in client-side logs, or cached. Anything that puts a live token where it can be read is a bug, because a leaked token is a stolen session.

A tampered or malformed token is mishandled. Change a character, truncate it, send null, send someone else's. The server should cleanly reject with a 401 — not 500, not silently succeed. For JWTs specifically, the classic test: does it accept a token with the signature stripped or the algorithm set to none? It must not.

API token test checklist

  • Expired token is rejected (capture one, wait past its lifetime, reuse it)
  • Logout invalidates the token server-side — replaying it after logout fails
  • Token scope is enforced: a read-only token can't write; a low-priv token can't reach high-priv data
  • A token for user A can't access user B's resources
  • No token in URLs, error responses, client logs, or caches
  • Tampered/malformed/null/wrong tokens get a clean 401, never a 500 or a success
  • (JWT) signature-stripped or alg: none tokens are rejected
  • Refresh flow: refreshing issues a new token and the old one stops working

How to test it without special tools

This is all doable with the API client you already use. Capture a real token from a normal login (browser dev tools or your API tool), then replay and mutate it: send it expired, send it after logout, send it to an endpoint it shouldn't reach, strip part of it. You're not breaking cryptography — you're checking that the server validates the token on every request instead of trusting it once. The mental shift is the whole technique: stop treating the token as an opaque "it works" string and start treating it as an input you can age, tamper with, and replay. The server has to re-earn its trust in that token on every call — your job is to confirm it does.

// RELATED QA.CODES RESOURCES


// related

Tutorials·13 June 2026 · 8 min read

The password reset bugs I always test for

Password reset is a deceptively risky flow — token reuse, expiry, enumeration, and session handling all hide here.

security-testingauthbugs