DEV Community

Turkay Kalenci
Turkay Kalenci

Posted on

An Ultimate Guide to Debugging JWTs in Your Web App

As developers, we are often forced to treat JSON Web Tokens (JWTs) as "magic black boxes." We get them from the auth server, stick them in a "Bearer" header, and pray.

The moment we see {"error": "Invalid Token"}, we panic.

Is it expired? Is the signature wrong? Is the server down? This guide will turn that black box into a clear glass box. This is a systematic process for debugging any JWT problem.

ANATOMY OF A JWT (THE 30-SECOND REFRESHER)
A JWT is just three strings, separated by dots: xxxx.yyyyy.zzzz

HEADER: Contains the algorithm (e.g., HS256).

PAYLOAD: Contains the data (e.g., userId, iat (Issued At), exp (Expiration Time)).

SIGNATURE: Ensures the token wasn't tampered with.

The Header and Payload are just Base64-encoded JSON. They are not encrypted. They are public.

THE DEBUGGING FLOWCHART: A STEP-BY-STEP GUIDE
Stop guessing. Follow this process.

STEP 1: IS IT BEING SENT? Before anything else, open your browser's Network tab.

Find your failed API request (it will be red, usually a 401 or 403 status).

Click on it. Go to the "Headers" tab.

Look at "Request Headers." Do you see Authorization: Bearer [long string]?

If not, your front-end code is failing to attach the token. Your token isn't "invalid," it's "missing."

STEP 2: IS IT MALFORMED? (THE MANUAL DECODE) If the token is being sent, copy that long string (without the "Bearer" part). Now, you need to see what's inside. Manually copying the middle part (the Payload) and pasting it into a generic Base64 decoder is slow and clunky.

This is why a dedicated JWT Debugger is essential. For my own workflow, I use a simple online tool (like the one at toolunify.com/en/encoder-decoder/jwt-debugger/) which instantly decodes the Header and Payload JSON for me.

Check the decoded payload. Is the JSON valid? Does it have the userId or sub (Subject) claim you expect?

STEP 3: IS IT EXPIRED? In that decoded payload, find the exp claim. It will look like this: 1678886400. This is a Unix timestamp. Go to a Unix Time converter (like the one in the toolunify.com suite) and check that date. If that time is in the past, your token is expired. Your front-end code needs to use its "refresh token" to get a new one.

STEP 4: IS THE SIGNATURE VALID? If the token is sent, is not malformed, and is not expired, then the only remaining option is a failed signature. This is a backend problem. This means the server (which has the "secret key") tried to verify the token and failed. This usually happens in two cases:

The token was tampered with on the client-side.

The server's secret key is wrong (e.g., dev and prod keys don't match).

CONCLUSION: STOP TREATING AUTH AS MAGIC
By following this flowchart, you've systematically ruled out every possibility.

Check Network Tab (Is it sent?)

Check Payload (Is it malformed?)

Check exp claim (Is it expired?)

If all else fails, blame the backend (Invalid Signature).

Stop guessing, and start debugging.

Top comments (0)