Skip to content

New lesson: Stateful vs Stateless Authentication #29814

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 15 commits into
base: main
Choose a base branch
from

Conversation

MaoShizhong
Copy link
Contributor

Because

As part of the Node revamp's 2nd milestone

This PR

  • Adds a new lesson comparing stateful and stateless authentication in the context of TOP

Issue

Closes #29735

Pull Request Requirements

  • I have thoroughly read and understand The Odin Project curriculum contributing guide
  • The title of this PR follows the location of change: brief description of change format, e.g. Intro to HTML and CSS lesson: Fix link text
  • The Because section summarizes the reason for this PR
  • The This PR section has a bullet point list describing the changes in this PR
  • If this PR addresses an open issue, it is linked in the Issue section
  • If any lesson files are included in this PR, they have been previewed with the Markdown preview tool to ensure it is formatted correctly
  • If any lesson files are included in this PR, they follow the Layout Style Guide

@github-actions github-actions bot added the Content: NodeJS Involves the NodeJS course label Jun 28, 2025
Not meant as a 'stateless/JWT is always bad in every context' thing
"or anyone" bit ends up reading awkwardly, and that example is focused on the impact of stale data. The impact of other users using copied tokens is already addressed in the next section.
Copy link
Member

@01zulfi 01zulfi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm 🚀

Loki is not related to Odin. That's a Marvel thing... oops
@@ -0,0 +1,68 @@
### Introduction

In previous lessons we covered both stateful authentication (demonstrated using sessions) and stateless authentication (using JWTs). You will often see both approaches out in the wild, which may not necessarily be implemented with sessions or JWTs specifically, but why the options? What are the pros and cons of each? How should I authenticate my applications? We will explore and compare our options in this lesson specifically in the context of projects for the rest of this course, where we implement authentication for the purpose of login persistence (session management).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In previous lessons we covered both stateful authentication (demonstrated using sessions) and stateless authentication (using JWTs). You will often see both approaches out in the wild, which may not necessarily be implemented with sessions or JWTs specifically, but why the options? What are the pros and cons of each? How should I authenticate my applications? We will explore and compare our options in this lesson specifically in the context of projects for the rest of this course, where we implement authentication for the purpose of login persistence (session management).
In previous lessons, we covered both stateful authentication (demonstrated using sessions) and stateless authentication (using JWTs). You will often see both approaches out in the wild, although not necessarily implemented using sessions or JWTs, so why choose one over the other? What are the pros and cons of each? How should you authenticate your applications? We will explore and compare our options in this lesson, specifically in the context of the remaining projects in this course, where authentication is used for login persistence (session management).

Slightly tighten up the sentence structure and avoid switching between pronouns (you vs I).


### Stateful vs stateless

Stateful authentication involves authentication data being stored server-side, such as in a session, while stateless authentication stores the data client-side, such as in a JWT. Why might one pick a stateless solution over a stateful one or vice versa, especially when you'll find many JWT tutorials online and various contrasting opinions across online forums?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Stateful authentication involves authentication data being stored server-side, such as in a session, while stateless authentication stores the data client-side, such as in a JWT. Why might one pick a stateless solution over a stateful one or vice versa, especially when you'll find many JWT tutorials online and various contrasting opinions across online forums?
Stateful authentication involves authentication data being stored server-side, such as in a session, while stateless authentication stores the data client-side, such as in a JWT. Why might one pick a stateless solution over a stateful one or vice versa?

Not sure this last part is necessary?


Stateful authentication involves authentication data being stored server-side, such as in a session, while stateless authentication stores the data client-side, such as in a JWT. Why might one pick a stateless solution over a stateful one or vice versa, especially when you'll find many JWT tutorials online and various contrasting opinions across online forums?

Stateless solutions reduce the amount of database calls needed per authenticated request, as a call is not needed to check the database for a matching session - the data is already there in the request and need only be verified. But is this actually a problem? At what point does this additional database call become a performance bottleneck in a stateful solution? While much larger products built with more complex architectures may well need to consider this, in all honesty, this is almost certainly not going to be an issue for many small projects, certainly not curriculum projects (and if it genuinely does, congratulations on the successful site!).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
Stateless solutions reduce the amount of database calls needed per authenticated request, as a call is not needed to check the database for a matching session - the data is already there in the request and need only be verified. But is this actually a problem? At what point does this additional database call become a performance bottleneck in a stateful solution? While much larger products built with more complex architectures may well need to consider this, in all honesty, this is almost certainly not going to be an issue for many small projects, certainly not curriculum projects (and if it genuinely does, congratulations on the successful site!).
Stateless solutions reduce the amount of database calls needed per authenticated request, as a call is not needed to check the database for a matching session - the data is already there in the request and needs only to be verified. But is this a problem? At what point does this additional database call become a performance bottleneck in a stateful solution? While much larger products built with more complex architectures may well need to consider this, it is almost certainly not going to be an issue for many small projects, certainly not curriculum projects (and if it genuinely does become an issue, congratulations on the successful site!).


Stateless solutions reduce the amount of database calls needed per authenticated request, as a call is not needed to check the database for a matching session - the data is already there in the request and need only be verified. But is this actually a problem? At what point does this additional database call become a performance bottleneck in a stateful solution? While much larger products built with more complex architectures may well need to consider this, in all honesty, this is almost certainly not going to be an issue for many small projects, certainly not curriculum projects (and if it genuinely does, congratulations on the successful site!).

But is there actually a negative to using something like JWTs for stateless authentication? Potentially: **authorization** and **invalidation**.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fleshes out the last sentence a bit

Suggested change
But is there actually a negative to using something like JWTs for stateless authentication? Potentially: **authorization** and **invalidation**.
But is there actually a negative to using something like JWTs for stateless authentication? Yes, particularly when it comes to **authorization** and **invalidation**.


Back in the JWT lesson, we demonstrated authenticating a request by verifying the JWT then using the ID from the payload to query the database for user data. This was intentional in order to avoid using the JWT for authorization, that is, the JWT only told us who was making the request but did not contain any personal information or things like roles and permissions.

Imagine if Odin was demoted from "god" to "demigod". meaning he's no longer allowed to access the god-only section of Valhalla. If the JWT stored role information, that information is now **stale** yet it still exists. As long as Odin still has that JWT, he could fool anyone into thinking he was still a full-blown god and not a demigod! Ideally the database holds the source of truth for these things, and we query it only once we have verified who is making the request. While this is still something that can occur when using sessions (i.e. storing permissions in the sessions themselves), at the very least session data is not stored client-side for anyone to see or take for themselves. This also leads us straight into the next issue to address.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nits

Suggested change
Imagine if Odin was demoted from "god" to "demigod". meaning he's no longer allowed to access the god-only section of Valhalla. If the JWT stored role information, that information is now **stale** yet it still exists. As long as Odin still has that JWT, he could fool anyone into thinking he was still a full-blown god and not a demigod! Ideally the database holds the source of truth for these things, and we query it only once we have verified who is making the request. While this is still something that can occur when using sessions (i.e. storing permissions in the sessions themselves), at the very least session data is not stored client-side for anyone to see or take for themselves. This also leads us straight into the next issue to address.
Imagine if Odin was demoted from "god" to "demigod", meaning he's no longer allowed to access the god-only section of Valhalla. If the JWT stored role information, that information is now **stale**, yet it still exists. As long as Odin still has that JWT, he could fool anyone into thinking he was still a full-blown god and not a demigod! Ideally, the database holds the source of truth for these things, and we query it only once we have verified who is making the request. While this can still occur when using sessions (i.e. storing permissions in the sessions themselves), at the very least session data is not stored client-side for anyone to see or take for themselves. This also leads us straight into the next issue to address.


#### Invalidation

How do you invalidate a session, such as when a user logs out? You just delete the session from the database. Now no matter who has the old session ID, there won't be a matching session and so it's now invalid. Now how do you do it with something like a JWT? As per the JWT lesson, you'd delete the JWT from the client. But does that actually mean the JWT is no longer valid?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this scans slightly better:

Suggested change
How do you invalidate a session, such as when a user logs out? You just delete the session from the database. Now no matter who has the old session ID, there won't be a matching session and so it's now invalid. Now how do you do it with something like a JWT? As per the JWT lesson, you'd delete the JWT from the client. But does that actually mean the JWT is no longer valid?
How do you invalidate a session, such as when a user logs out? You just delete the session from the database. Now, no matter who has the old session ID, there won't be a matching session, and so it's now invalid. Now, how do you invalidate something like a JWT? As per the JWT lesson, you'd delete the JWT from the client. But does that actually mean the JWT is no longer valid?


The same applies to now-demigod Odin. His father Borr took away his "My name is Odin and I'm a god" token but luckily, Loki had a copy for him, so now Odin can go around pretending to be a full-blown god again. Even worse, Loki could go around pretending to be Odin himself!

Since the server does not store the tokens, it cannot directly invalidate them without changing the secret used to sign them, but then that will invalidate *every* users' tokens. Keeping a server-side list of revoked tokens would just make things stateful (like a more complex version of sessions), since every authenticated request must query that revocation list before verifying any tokens. Setting a super-short expiry time like a few minutes would definitely reduce how long a malicious actor could use a stolen JWT to wreak havoc, but then that'd ruin the user experience for everyone else if they could only stay logged in for a few minutes at a time (though this is of course sometimes an desirable security feature, like with many banking websites).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nits:

Suggested change
Since the server does not store the tokens, it cannot directly invalidate them without changing the secret used to sign them, but then that will invalidate *every* users' tokens. Keeping a server-side list of revoked tokens would just make things stateful (like a more complex version of sessions), since every authenticated request must query that revocation list before verifying any tokens. Setting a super-short expiry time like a few minutes would definitely reduce how long a malicious actor could use a stolen JWT to wreak havoc, but then that'd ruin the user experience for everyone else if they could only stay logged in for a few minutes at a time (though this is of course sometimes an desirable security feature, like with many banking websites).
Since the server does not store the tokens, it cannot directly invalidate them without changing the secret used to sign them, but then that will invalidate every user's tokens. Keeping a server-side list of revoked tokens would just make things stateful (like a more complex version of sessions), since every authenticated request must query that revocation list before verifying any tokens. Setting a super-short expiry time like a few minutes would definitely reduce how long a malicious actor could use a stolen JWT to wreak havoc, but then that'd ruin the user experience for everyone else if they could only stay logged in for a few minutes at a time (though this can be a desirable security feature, like with many banking websites).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Content: NodeJS Involves the NodeJS course
Projects
None yet
Development

Successfully merging this pull request may close these issues.

New Lesson: Stateful vs Stateless Auth
3 participants