> ## Content Index
> Fetch the complete content index at: https://securinglaravel.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Security Tip: Your JWT Might Be a Forever Key!
- URL: https://securinglaravel.com/security-tip-your-jwt-might-be-a-forever-key/
- Published: 2026-03-09T07:08:28.000Z
- Updated: 2026-03-09T07:08:28.000Z
- Description: [Tip #127] Without an `exp` claim, a JWT can remain valid forever, turning a leaked token into permanent access.
- Author: Stephen Rees-Carter
- Tags: Security Tips, Authentication, Authorisation, JWT, Cryptography

JSON Web Tokens (JWT) were designed as a tamper-resistant method of passing data between different systems, in the form of a set of claims. These claims are typically used as some part of an authentication and authorisation system - asserting who the bearer is and what they are allowed to do. Note that JWTs aren't encrypted, they're just signed to prevent modification.

JWTs look something like this:

```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.KMUFsIDTnFmyG3nMiGM6H9FNFUROf3wh7SmqJp-QV30
```

Example JWT

If you recognise the two `eyJ` in there, you'll quickly figure out that you're looking at a couple of Base64URL encoded JSON strings, separated by `.`:

```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
{"alg":"HS256","typ":"JWT"}

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0
{"sub":"1234567890","name":"John Doe","admin":true,"iat":1516239022}

KMUFsIDTnFmyG3nMiGM6H9FNFUROf3wh7SmqJp-QV30
<HMAC Signature>
```

JWT Decoded

We'll have to dig into how JWTs work in greater detail another time, but for now I just want to point out something specific that is missing here... 

In the middle section, we have the user `John Doe`, identified by `sub=1234567890` (their user ID), marked as `admin=true`, with this token issued at `iat=1516239022` (18th January 2018).

I often see JWTs used to authenticate users, either via some form of API, in an SPA, or via magic links. But the problem is, this token is 8 years old (at time of writing), and as far as the application is concerned **it's still perfectly valid!** If the application accepts this JWT, then anyone who gains access to it will become Admin John Doe!

John might have left the company, their requests might have been logged somewhere and recovered in a data breach, their emails might have been compromised, etc. The possibilities are endless... like this token. It is effectively a **forever key** that will always allow the bearer in.

Oh, and **JWTs cannot be revoked** without some form of server-side state.

Without adding server-side state, rotating keys, or maintaining blocklists, the easiest way to limit abuse is to add an Expiration Time (`exp`) claim. This sets a limited time window on the JWT, so if it's stolen or discovered later, it's no longer useful.

For example, this payload gives the JWT one month validity:

```
{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true,
  "iat": 1516239022,
  "exp": 1518881422
}
```

It would have stopped working on the 18th February 2018, and be completely useless to anyone who discovers it after this date. 

Sure, you have to issue new JWTs periodically, **but the alternative is a forever key you are unaware of and cannot block.**

So make sure your JWTs have a reasonable `exp` set! 

*Oh, and make sure your JWT package actually enforces `exp`, apparently not all of them do by default.* 🤦

---

***If you found this security tip useful?* 👍**  
[*Subscribe now*](#/portal/signup) *to get weekly* [***Security Tips***](https://securinglaravel.com/tag/tips/) *straight to your inbox, filled with practical, actionable advice to help you build safer apps.*

***Want to learn more?* 🤓**  
*Upgrade to a* [*Premium Subscription*](#/portal/signup) *for exclusive monthly* [**In Depth* articles*](https://securinglaravel.com/tag/in-depth/)*, or support my work with a* [*one-off tip*](#/portal/support)*! Your support directly funds my security work in the Laravel community.* 🥰

**Need a second set of eyes on your code?** 
*Book in a* [*Laravel Security Audit and Penetration Test*](https://stephenreescarter.net/laravel-security-audits-and-pentesting/?utm%5Fsource=securinglaravel.com) *today! I also offer budget-friendly* [*Security Reviews*](https://stephenreescarter.net/laravel-security-reviews/?utm%5Fsource=securinglaravel.com) *too.*

*Finally, connect with me on* [*Bluesky*](https://bsky.app/profile/valorin.bsky.social?ref=securinglaravel.com)*, or* [*other socials*](https://pinkary.com/@valorin?ref=securinglaravel.com)*, and check out* [*Practical Laravel Security*](https://practicallaravelsecurity.com/?utm%5Fsource=securinglaravel.com)*, my interactive course designed to boost your Laravel security skills.*1