To test JWT handling, send the API tokens it should refuse: one with a changed claim, one with the signature removed, one using the none algorithm, one expired, and one issued for a different audience. Every one should return an authentication failure, never a success or a server error.
What a JWT test proves
A JSON Web Token is a signed claim set. The API must check the signature, the algorithm, the issuer, the audience and the expiry before it trusts any claim. RFC 8725 lists these as recommended practice: verify the algorithm against an allowed list, validate all cryptographic operations, validate issuer and subject, and use and check the audience claim.
Test cases
| Test | What you send | Expected result |
|---|---|---|
| Tampered claim | Change the role claim, keep the old signature | 401 |
| Stripped signature | Remove the signature part | 401 |
| None algorithm | Header says none, no signature | 401 |
| Algorithm swap | Change the algorithm to one the key was not made for | 401 |
| Expired token | An exp time in the past | 401 |
| Wrong audience | A valid token for another service | 401 or 403 |
| Wrong issuer | A token from a different issuer | 401 |
| Garbage token | Random text | 401, not 500 |
Steps
- Log in as a test user and capture a real token.
- Decode it in a local tool, never an online decoder, since tokens are credentials.
- Create each modified variant from the table. Re-signing with your own key covers the case where the server trusts any signature.
- Replay each variant against a protected endpoint and record the status code.
- Check headers that name keys or key locations. RFC 8725 says not to trust received claims blindly, and warns about SSRF through key URL headers, so test whether a header pointing at your own server is fetched.
- Check that a token for one token kind, such as a refresh token, is rejected where an access token is expected.
Reading the results
A 500 on a malformed token is a finding even if access is denied, because it shows the parser is not handling hostile input. A 200 on any row is a serious finding.
Fix direction
Configure the library with an explicit allowed algorithm list, require issuer and audience, keep access token lifetimes short, and use separate typing for different token kinds so they cannot be swapped.
Try it yourself
Open the authentication finding and see which token variant was accepted.
Click through it at your own pace, or open it full screen.
Quick check
Is decoding a JWT the same as verifying it?
No. Decoding only reads the claims. Verification checks the signature and the claims against your rules.
Should I paste a real token into an online decoder?
No. Treat tokens as passwords. Decode locally and use short lived tokens for testing.
Where Safeguard fits
Safeguard offers dependency and SBOM scanning, reachability analysis and policies and gates that can block a pull request, so the libraries behind your app are checked alongside the app itself. You can try a free scan at gold.safeguard.sh/scan.
Sources
- RFC 8725 on JSON Web Token security (BCP 225)
- OWASP REST Assessment Cheat Sheet
- OWASP API2:2023 Broken Authentication
Last reviewed: 19 October 2026.