From a0fcca9b60d5a22edd94ac37212d9df263257861 Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Mon, 23 Jun 2025 23:29:38 +0100 Subject: [PATCH 01/24] Write intro --- .../stateful_vs_stateless_authentication.md | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 nodeJS/authentication/stateful_vs_stateless_authentication.md diff --git a/nodeJS/authentication/stateful_vs_stateless_authentication.md b/nodeJS/authentication/stateful_vs_stateless_authentication.md new file mode 100644 index 00000000000..7691d7e2d30 --- /dev/null +++ b/nodeJS/authentication/stateful_vs_stateless_authentication.md @@ -0,0 +1,27 @@ +### 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? + +### Lesson overview + +This section contains a general overview of topics that you will learn in this lesson. + +- Compare pros and cons of stateful and stateless approaches to authentication. + +### Assignment + +
+ +
+ +### Knowledge check + +The following questions are an opportunity to reflect on key topics in this lesson. If you can't answer a question, click on it to review the material, but keep in mind you are not expected to memorize or master this knowledge. + +- []() + +### Additional resources + +This section contains helpful links to related content. It isn't required, so consider it supplemental. + +- It looks like this lesson doesn't have any additional resources yet. Help us expand this section by contributing to our curriculum. From e007ec4e0046837d80c7d4501ba0ca25dda998d2 Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Sat, 28 Jun 2025 22:43:00 +0100 Subject: [PATCH 02/24] Write intro to comparison To lead into addressing two main issues --- .../stateful_vs_stateless_authentication.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/nodeJS/authentication/stateful_vs_stateless_authentication.md b/nodeJS/authentication/stateful_vs_stateless_authentication.md index 7691d7e2d30..02c2c1a2981 100644 --- a/nodeJS/authentication/stateful_vs_stateless_authentication.md +++ b/nodeJS/authentication/stateful_vs_stateless_authentication.md @@ -8,6 +8,14 @@ This section contains a general overview of topics that you will learn in this l - Compare pros and cons of stateful and stateless approaches to authentication. +### 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? + +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**. + ### Assignment
From 78653ccb1720f1e0ee0896571334df117f38cd89 Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Sun, 29 Jun 2025 00:08:01 +0100 Subject: [PATCH 03/24] Write content on stateless caveats --- .../stateful_vs_stateless_authentication.md | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/nodeJS/authentication/stateful_vs_stateless_authentication.md b/nodeJS/authentication/stateful_vs_stateless_authentication.md index 02c2c1a2981..706f36f78ed 100644 --- a/nodeJS/authentication/stateful_vs_stateless_authentication.md +++ b/nodeJS/authentication/stateful_vs_stateless_authentication.md @@ -16,6 +16,26 @@ Stateless solutions reduce the amount of database calls needed per authenticated But is there actually a negative to using something like JWTs for stateless authentication? Potentially: **authorization** and **invalidation**. +### Authentication and authorization + +Back in the JWT lesson, we demonstrated authenticating a request by verifying the JWT then using the ID from the payload to query the databasse 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 (or anyone) still has that JWT, they could fool anyone into thinking they were still a 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 a possibility when using sessions (e.g. 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 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? + +JWTs are much harder to invalidate. Say you generate one with a 2-day expiry and the client then logs out, deleting it from whatever storage medium was used. The client no longer has the token but since it's just text, anyone else who has that text could continue to use it and it will still be valid until expiry. This could have been obtained via any number of malicious attack methods, including [cross-site scripting (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting) and [cross-site request forgery (CSRF)](https://en.wikipedia.org/wiki/Cross-site_request_forgery). At the most basic level, your pesky sibling could have went on your computer, opened devtools, then copied down the JWT value to use on their machine. + +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, 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 of course this is sometimes an intended security feature, like with many banking websites). + +#### A hybrid approach + +As a result, some services implement a hybrid stateful+stateless approach, such as using two tokens: "access" and "refresh". The main JWT is the "access token" and has a very short expiry. The client also receives a second "refresh token", and *that* token is stored server-side (making it the stateful part). If the access token is still valid, it's used as normal. If it has expired, the server checks if the refresh token is valid. If it is, the server can generate a fresh access token for use, but if not, it can unauthorize the request. + +This comes with the benefit of not needing the additional database call for authentication data for any requests made with a valid access token, while retaining the ability to invalidate refresh tokens by deleting them from the database. The short-expiry access token then reduces the duration of potential vulnerability. + ### Assignment
From 9fe0b67edb3c7347ad898ae681341a4f05edfc59 Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Sun, 29 Jun 2025 00:16:41 +0100 Subject: [PATCH 04/24] Recommend authentication approach for remaining TOP projects --- .../stateful_vs_stateless_authentication.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/nodeJS/authentication/stateful_vs_stateless_authentication.md b/nodeJS/authentication/stateful_vs_stateless_authentication.md index 706f36f78ed..f4766b606f5 100644 --- a/nodeJS/authentication/stateful_vs_stateless_authentication.md +++ b/nodeJS/authentication/stateful_vs_stateless_authentication.md @@ -26,9 +26,9 @@ Imagine if Odin was demoted from "god" to "demigod". meaning he's no longer allo 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? -JWTs are much harder to invalidate. Say you generate one with a 2-day expiry and the client then logs out, deleting it from whatever storage medium was used. The client no longer has the token but since it's just text, anyone else who has that text could continue to use it and it will still be valid until expiry. This could have been obtained via any number of malicious attack methods, including [cross-site scripting (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting) and [cross-site request forgery (CSRF)](https://en.wikipedia.org/wiki/Cross-site_request_forgery). At the most basic level, your pesky sibling could have went on your computer, opened devtools, then copied down the JWT value to use on their machine. +JWTs are much harder to invalidate. Say you generate one with a 2-day expiry and the client then logs out, deleting it from whatever storage medium was used. The client no longer has the token but since it's just text, anyone else who has that text could continue to use it and it will still be valid until expiry. This could have been obtained via any number of malicious attack methods, including [cross-site scripting (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting) and [cross-site request forgery (CSRF)](https://en.wikipedia.org/wiki/Cross-site_request_forgery), especially if the token is stored somewhere like in local storage. At the most basic level, a pesky sibling/roommate could have gone on your computer, opened devtools, then copied down the JWT value to use on their machine. -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, 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 of course this is sometimes an intended 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* users' tokens. Keeping a server-side list of revoked tokens would just make things stateful (almost 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 of course this is sometimes an intended security feature, like with many banking websites). #### A hybrid approach @@ -36,6 +36,12 @@ As a result, some services implement a hybrid stateful+stateless approach, such This comes with the benefit of not needing the additional database call for authentication data for any requests made with a valid access token, while retaining the ability to invalidate refresh tokens by deleting them from the database. The short-expiry access token then reduces the duration of potential vulnerability. +### Authentication and TOP projects + +For the purposes of TOP projects going forward, stick to stateful authentication using sessions. None of this means stateless authentication or JWTs are inherently bad, only that for the purposes of projects in this curriculum, it's not really worth the additional complexity trying to implement a more secure stateless solution when you can use a stateful one instead. "Scaling" is only relevant in context, and curriculum projects or even many small personal projects are seldom going to get to the point where stateful solutions will be a genuine performance bottleneck that requires a stateless solution instead. + +There are plenty of good and bad implementations of authentication out in the wild, both stateful and stateless, hence it's good to be aware of the concepts and mechanisms. You may end up working with things in the future where stateless authentication (whether with JWTs or other types of tokens) makes perfect sense. As far as TOP projects are concerned though, that isn't so necessary. + ### Assignment
From 44af6d0619f51fec65d3044621743ed341eb340a Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Sun, 29 Jun 2025 00:36:02 +0100 Subject: [PATCH 05/24] Add assignment and knowledge check contents --- .../authentication/stateful_vs_stateless_authentication.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/nodeJS/authentication/stateful_vs_stateless_authentication.md b/nodeJS/authentication/stateful_vs_stateless_authentication.md index f4766b606f5..1d235b49f17 100644 --- a/nodeJS/authentication/stateful_vs_stateless_authentication.md +++ b/nodeJS/authentication/stateful_vs_stateless_authentication.md @@ -46,13 +46,18 @@ There are plenty of good and bad implementations of authentication out in the wi
+1. Read ["Stop using JWT for sessions"](http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/) for a breakdown of why the proposed benefits of JWTs (for essentially the same thing as sessions) may not be worth the complexities and potential vulnerabilities. +1. Read another take on [avoiding JWTs to implement browser sessions](https://ianlondon.github.io/posts/dont-use-jwts-for-sessions/). +
### Knowledge check The following questions are an opportunity to reflect on key topics in this lesson. If you can't answer a question, click on it to review the material, but keep in mind you are not expected to memorize or master this knowledge. -- []() +- [Why might a product want to use stateless authentication instead of stateful?](#stateful-vs-stateless) +- [What issues might one face with stale data in authentication tokens?](#authentication-and-authorization) +- [What issues might stateless authentication have regarding invalidation?](#invalidation) ### Additional resources From 737f3834b5dfc6e00a4cc7e45e14384af1a7cbb6 Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Sun, 29 Jun 2025 00:41:23 +0100 Subject: [PATCH 06/24] Expand on invalidation<->stale data --- .../authentication/stateful_vs_stateless_authentication.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/nodeJS/authentication/stateful_vs_stateless_authentication.md b/nodeJS/authentication/stateful_vs_stateless_authentication.md index 1d235b49f17..87768f522f0 100644 --- a/nodeJS/authentication/stateful_vs_stateless_authentication.md +++ b/nodeJS/authentication/stateful_vs_stateless_authentication.md @@ -10,7 +10,7 @@ This section contains a general overview of topics that you will learn in this l ### 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? +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!). @@ -28,6 +28,8 @@ How do you invalidate a session, such as when a user logs out? You just delete t JWTs are much harder to invalidate. Say you generate one with a 2-day expiry and the client then logs out, deleting it from whatever storage medium was used. The client no longer has the token but since it's just text, anyone else who has that text could continue to use it and it will still be valid until expiry. This could have been obtained via any number of malicious attack methods, including [cross-site scripting (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting) and [cross-site request forgery (CSRF)](https://en.wikipedia.org/wiki/Cross-site_request_forgery), especially if the token is stored somewhere like in local storage. At the most basic level, a pesky sibling/roommate could have gone on your computer, opened devtools, then copied down the JWT value to use on their machine. +The same applies to now-demigod Odin. His father Borr took away his "god" token but luckily, his brother Vili had a copy so now Odin can go around pretending to be a full-blown god again. Hence the lack of invalidation becomes a particular issue for stale data in tokens that may contain things like authorization data. + 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 (almost 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 of course this is sometimes an intended security feature, like with many banking websites). #### A hybrid approach @@ -40,7 +42,7 @@ This comes with the benefit of not needing the additional database call for auth For the purposes of TOP projects going forward, stick to stateful authentication using sessions. None of this means stateless authentication or JWTs are inherently bad, only that for the purposes of projects in this curriculum, it's not really worth the additional complexity trying to implement a more secure stateless solution when you can use a stateful one instead. "Scaling" is only relevant in context, and curriculum projects or even many small personal projects are seldom going to get to the point where stateful solutions will be a genuine performance bottleneck that requires a stateless solution instead. -There are plenty of good and bad implementations of authentication out in the wild, both stateful and stateless, hence it's good to be aware of the concepts and mechanisms. You may end up working with things in the future where stateless authentication (whether with JWTs or other types of tokens) makes perfect sense. As far as TOP projects are concerned though, that isn't so necessary. +There are plenty of good and bad implementations of authentication out in the wild, both stateful and stateless, hence it's good to be aware of the concepts and mechanisms. You may end up working with things in the future where stateless authentication (whether with JWTs or other types of tokens) makes perfect sense. As far as TOP projects are concerned though, that isn't quite the case; simply put, our use case for authenticating requests from an SPA and separate server is one where stateful sessions are a very appropriate solution, more so than stateless JWTs. ### Assignment From 9c59f9ae1f9b8e9aea07234e06fb603015224f5f Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Sun, 29 Jun 2025 00:49:24 +0100 Subject: [PATCH 07/24] Fix typo --- nodeJS/authentication/stateful_vs_stateless_authentication.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nodeJS/authentication/stateful_vs_stateless_authentication.md b/nodeJS/authentication/stateful_vs_stateless_authentication.md index 87768f522f0..8c5530fdd3f 100644 --- a/nodeJS/authentication/stateful_vs_stateless_authentication.md +++ b/nodeJS/authentication/stateful_vs_stateless_authentication.md @@ -18,7 +18,7 @@ But is there actually a negative to using something like JWTs for stateless auth ### Authentication and authorization -Back in the JWT lesson, we demonstrated authenticating a request by verifying the JWT then using the ID from the payload to query the databasse 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. +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 (or anyone) still has that JWT, they could fool anyone into thinking they were still a 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 a possibility when using sessions (e.g. 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 leads us straight into the next issue to address. @@ -48,6 +48,7 @@ There are plenty of good and bad implementations of authentication out in the wi
+ 1. Read ["Stop using JWT for sessions"](http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/) for a breakdown of why the proposed benefits of JWTs (for essentially the same thing as sessions) may not be worth the complexities and potential vulnerabilities. 1. Read another take on [avoiding JWTs to implement browser sessions](https://ianlondon.github.io/posts/dont-use-jwts-for-sessions/). From ed494e4ff708e554b05035071910abc92f91d2cb Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Sun, 29 Jun 2025 00:54:18 +0100 Subject: [PATCH 08/24] Remove ineffective codespell:ignore comment --- nodeJS/authentication/stateful_vs_stateless_authentication.md | 1 - 1 file changed, 1 deletion(-) diff --git a/nodeJS/authentication/stateful_vs_stateless_authentication.md b/nodeJS/authentication/stateful_vs_stateless_authentication.md index 8c5530fdd3f..3ca6655171d 100644 --- a/nodeJS/authentication/stateful_vs_stateless_authentication.md +++ b/nodeJS/authentication/stateful_vs_stateless_authentication.md @@ -48,7 +48,6 @@ There are plenty of good and bad implementations of authentication out in the wi
- 1. Read ["Stop using JWT for sessions"](http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/) for a breakdown of why the proposed benefits of JWTs (for essentially the same thing as sessions) may not be worth the complexities and potential vulnerabilities. 1. Read another take on [avoiding JWTs to implement browser sessions](https://ianlondon.github.io/posts/dont-use-jwts-for-sessions/). From 1bcc6b841030e4889278cb0cf835938e240b9c65 Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Sun, 29 Jun 2025 01:14:03 +0100 Subject: [PATCH 09/24] Emphasise context of lesson's comparison Not meant as a 'stateless/JWT is always bad in every context' thing --- nodeJS/authentication/stateful_vs_stateless_authentication.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nodeJS/authentication/stateful_vs_stateless_authentication.md b/nodeJS/authentication/stateful_vs_stateless_authentication.md index 3ca6655171d..862987bbd4a 100644 --- a/nodeJS/authentication/stateful_vs_stateless_authentication.md +++ b/nodeJS/authentication/stateful_vs_stateless_authentication.md @@ -1,6 +1,6 @@ ### 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? +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). ### Lesson overview From 6b6998ff6daaeefddc6c16773592852d5482e3d9 Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Sun, 29 Jun 2025 09:22:42 +0100 Subject: [PATCH 10/24] Rephrase invalidating Odin token example --- nodeJS/authentication/stateful_vs_stateless_authentication.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nodeJS/authentication/stateful_vs_stateless_authentication.md b/nodeJS/authentication/stateful_vs_stateless_authentication.md index 862987bbd4a..a56694a1f44 100644 --- a/nodeJS/authentication/stateful_vs_stateless_authentication.md +++ b/nodeJS/authentication/stateful_vs_stateless_authentication.md @@ -28,9 +28,9 @@ How do you invalidate a session, such as when a user logs out? You just delete t JWTs are much harder to invalidate. Say you generate one with a 2-day expiry and the client then logs out, deleting it from whatever storage medium was used. The client no longer has the token but since it's just text, anyone else who has that text could continue to use it and it will still be valid until expiry. This could have been obtained via any number of malicious attack methods, including [cross-site scripting (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting) and [cross-site request forgery (CSRF)](https://en.wikipedia.org/wiki/Cross-site_request_forgery), especially if the token is stored somewhere like in local storage. At the most basic level, a pesky sibling/roommate could have gone on your computer, opened devtools, then copied down the JWT value to use on their machine. -The same applies to now-demigod Odin. His father Borr took away his "god" token but luckily, his brother Vili had a copy so now Odin can go around pretending to be a full-blown god again. Hence the lack of invalidation becomes a particular issue for stale data in tokens that may contain things like authorization data. +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 his son, Loki, had a copy. So now Odin can go around pretending to be a full-blown god again. Even worse, Loki could go around pretending to be his father! -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 (almost 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 of course this is sometimes an intended 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* 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). #### A hybrid approach From 8d529ec6d0ee46cc96aaa6c773c60aeab9779e11 Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Sun, 29 Jun 2025 09:23:07 +0100 Subject: [PATCH 11/24] Fix subsection heading levels --- nodeJS/authentication/stateful_vs_stateless_authentication.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nodeJS/authentication/stateful_vs_stateless_authentication.md b/nodeJS/authentication/stateful_vs_stateless_authentication.md index a56694a1f44..aad9c8260ab 100644 --- a/nodeJS/authentication/stateful_vs_stateless_authentication.md +++ b/nodeJS/authentication/stateful_vs_stateless_authentication.md @@ -16,13 +16,13 @@ Stateless solutions reduce the amount of database calls needed per authenticated But is there actually a negative to using something like JWTs for stateless authentication? Potentially: **authorization** and **invalidation**. -### Authentication and authorization +#### Authentication and authorization 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 (or anyone) still has that JWT, they could fool anyone into thinking they were still a 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 a possibility when using sessions (e.g. 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 leads us straight into the next issue to address. -### Invalidation +#### 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? From e7cf5f2ad1062944c7c284136bfc0780ef373866 Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Sun, 29 Jun 2025 09:27:58 +0100 Subject: [PATCH 12/24] Rephrase initial Odin demotion example "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. --- nodeJS/authentication/stateful_vs_stateless_authentication.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nodeJS/authentication/stateful_vs_stateless_authentication.md b/nodeJS/authentication/stateful_vs_stateless_authentication.md index aad9c8260ab..e14a0619d7f 100644 --- a/nodeJS/authentication/stateful_vs_stateless_authentication.md +++ b/nodeJS/authentication/stateful_vs_stateless_authentication.md @@ -20,7 +20,7 @@ But is there actually a negative to using something like JWTs for stateless auth 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 (or anyone) still has that JWT, they could fool anyone into thinking they were still a 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 a possibility when using sessions (e.g. 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 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 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. #### Invalidation From 5c6ddc8c5c955f28b0f354864ad9fea0551948df Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Sun, 29 Jun 2025 09:33:20 +0100 Subject: [PATCH 13/24] Streamline wording for access/refresh tokens --- nodeJS/authentication/stateful_vs_stateless_authentication.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nodeJS/authentication/stateful_vs_stateless_authentication.md b/nodeJS/authentication/stateful_vs_stateless_authentication.md index e14a0619d7f..de973d4bc94 100644 --- a/nodeJS/authentication/stateful_vs_stateless_authentication.md +++ b/nodeJS/authentication/stateful_vs_stateless_authentication.md @@ -34,9 +34,9 @@ Since the server does not store the tokens, it cannot directly invalidate them w #### A hybrid approach -As a result, some services implement a hybrid stateful+stateless approach, such as using two tokens: "access" and "refresh". The main JWT is the "access token" and has a very short expiry. The client also receives a second "refresh token", and *that* token is stored server-side (making it the stateful part). If the access token is still valid, it's used as normal. If it has expired, the server checks if the refresh token is valid. If it is, the server can generate a fresh access token for use, but if not, it can unauthorize the request. +As a result, some services implement a hybrid stateful+stateless approach, such as using two tokens: "access" and "refresh". The main JWT is the "access token" and has a very short expiry. The client also receives a second "refresh token" with a much longer expiry, and *that* token is stored server-side (making it the stateful part). If the access token is still valid, it's used as normal. If it has expired, the server checks if the refresh token is valid. If it is, the server can generate a fresh access token for use, but if not, it can unauthorize the request. -This comes with the benefit of not needing the additional database call for authentication data for any requests made with a valid access token, while retaining the ability to invalidate refresh tokens by deleting them from the database. The short-expiry access token then reduces the duration of potential vulnerability. +This comes with the benefit of not needing the additional database call for authentication data for any requests made with a valid access token, and the long-expiry refresh token retains the longer login persistence for a better user experience. Since the refresh tokens can be invalidated by deleting them from the database, the short-expiry access token reduces the duration of potential vulnerability. ### Authentication and TOP projects From 62708ab637abb8a8f9e4acf4b85851be2993ea8d Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Sun, 29 Jun 2025 10:04:35 +0100 Subject: [PATCH 14/24] Fix mythological inaccuracy Loki is not related to Odin. That's a Marvel thing... oops --- nodeJS/authentication/stateful_vs_stateless_authentication.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nodeJS/authentication/stateful_vs_stateless_authentication.md b/nodeJS/authentication/stateful_vs_stateless_authentication.md index de973d4bc94..3cb2313edee 100644 --- a/nodeJS/authentication/stateful_vs_stateless_authentication.md +++ b/nodeJS/authentication/stateful_vs_stateless_authentication.md @@ -28,7 +28,7 @@ How do you invalidate a session, such as when a user logs out? You just delete t JWTs are much harder to invalidate. Say you generate one with a 2-day expiry and the client then logs out, deleting it from whatever storage medium was used. The client no longer has the token but since it's just text, anyone else who has that text could continue to use it and it will still be valid until expiry. This could have been obtained via any number of malicious attack methods, including [cross-site scripting (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting) and [cross-site request forgery (CSRF)](https://en.wikipedia.org/wiki/Cross-site_request_forgery), especially if the token is stored somewhere like in local storage. At the most basic level, a pesky sibling/roommate could have gone on your computer, opened devtools, then copied down the JWT value to use on their machine. -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 his son, Loki, had a copy. So now Odin can go around pretending to be a full-blown god again. Even worse, Loki could go around pretending to be his father! +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). From 6f0fa79399ecdb2075a9275ca77c45d3a0c23e78 Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Sun, 29 Jun 2025 10:14:32 +0100 Subject: [PATCH 15/24] Fix grammar --- nodeJS/authentication/stateful_vs_stateless_authentication.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nodeJS/authentication/stateful_vs_stateless_authentication.md b/nodeJS/authentication/stateful_vs_stateless_authentication.md index 3cb2313edee..379661d57b0 100644 --- a/nodeJS/authentication/stateful_vs_stateless_authentication.md +++ b/nodeJS/authentication/stateful_vs_stateless_authentication.md @@ -26,7 +26,7 @@ Imagine if Odin was demoted from "god" to "demigod". meaning he's no longer allo 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? -JWTs are much harder to invalidate. Say you generate one with a 2-day expiry and the client then logs out, deleting it from whatever storage medium was used. The client no longer has the token but since it's just text, anyone else who has that text could continue to use it and it will still be valid until expiry. This could have been obtained via any number of malicious attack methods, including [cross-site scripting (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting) and [cross-site request forgery (CSRF)](https://en.wikipedia.org/wiki/Cross-site_request_forgery), especially if the token is stored somewhere like in local storage. At the most basic level, a pesky sibling/roommate could have gone on your computer, opened devtools, then copied down the JWT value to use on their machine. +JWTs are much harder to invalidate. Say you generate one with a 2-day expiry and the client then logs out, deleting it from whatever storage medium was used. The client no longer has the token but since it's just text, anyone else who has that text could continue to use it and it would still be valid until expiry. The token could have been obtained via any number of malicious attack methods, including [cross-site scripting (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting) and [cross-site request forgery (CSRF)](https://en.wikipedia.org/wiki/Cross-site_request_forgery), especially if the token was stored somewhere like in local storage. At the most basic level, a pesky sibling/roommate could have gone on your computer, opened devtools, then copied down the JWT value to use on their machine. 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! From 6a1aea36f7e45e94604996bd3a401190962530ec Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Sun, 27 Jul 2025 16:35:28 +0100 Subject: [PATCH 16/24] Rename lesson Updated scoped and intent --- ...teless_authentication.md => session_management_in_practice.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename nodeJS/authentication/{stateful_vs_stateless_authentication.md => session_management_in_practice.md} (100%) diff --git a/nodeJS/authentication/stateful_vs_stateless_authentication.md b/nodeJS/authentication/session_management_in_practice.md similarity index 100% rename from nodeJS/authentication/stateful_vs_stateless_authentication.md rename to nodeJS/authentication/session_management_in_practice.md From 2c1198cbc7f62b8b9a7d96a4026424444d87b604 Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Sun, 27 Jul 2025 16:39:51 +0100 Subject: [PATCH 17/24] Update intro/lesson overview with updated scope --- nodeJS/authentication/session_management_in_practice.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nodeJS/authentication/session_management_in_practice.md b/nodeJS/authentication/session_management_in_practice.md index 379661d57b0..9aa86ab0444 100644 --- a/nodeJS/authentication/session_management_in_practice.md +++ b/nodeJS/authentication/session_management_in_practice.md @@ -1,12 +1,13 @@ ### 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). +In previous lessons, we covered both stateful authentication (demonstrated using server-side sessions) and stateless authentication (using JWTs) for the purpose of session management (persisting logins). You will often see both approaches out in the wild, although not necessarily implemented using sessions or JWTs specifically, but still, why the options? What are the pros and cons of each? How should you authenticate your applications? In this lesson, we will explore and compare our options specifically in the context of projects for the rest of this course, where authentication is used for session management. We will also touch on challenges you may face when it comes to authentication and deployment. ### Lesson overview This section contains a general overview of topics that you will learn in this lesson. -- Compare pros and cons of stateful and stateless approaches to authentication. +- Compare pros and cons of stateful and stateless approaches to authentication and session management. +- Explore ways to handle authentication when the client and server are not hosted on the same domain. ### Stateful vs stateless From 3e0b841da0604929184bd7b4961aeb1a25d8d0ad Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Sun, 27 Jul 2025 16:46:06 +0100 Subject: [PATCH 18/24] Streamline verbiage Co-authored-by: Asartea <76259120+Asartea@users.noreply.github.com> --- .../session_management_in_practice.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/nodeJS/authentication/session_management_in_practice.md b/nodeJS/authentication/session_management_in_practice.md index 9aa86ab0444..623f661dd55 100644 --- a/nodeJS/authentication/session_management_in_practice.md +++ b/nodeJS/authentication/session_management_in_practice.md @@ -11,27 +11,27 @@ This section contains a general overview of topics that you will learn in this l ### 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? +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? -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 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 become an issue, congratulations on the successful site!). -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**. #### Authentication and authorization 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. +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? +How do you invalidate a session, such as when a user logs out? You just delete the session from the database, then no matter who has the old session ID, there won't be a matching session, 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? JWTs are much harder to invalidate. Say you generate one with a 2-day expiry and the client then logs out, deleting it from whatever storage medium was used. The client no longer has the token but since it's just text, anyone else who has that text could continue to use it and it would still be valid until expiry. The token could have been obtained via any number of malicious attack methods, including [cross-site scripting (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting) and [cross-site request forgery (CSRF)](https://en.wikipedia.org/wiki/Cross-site_request_forgery), especially if the token was stored somewhere like in local storage. At the most basic level, a pesky sibling/roommate could have gone on your computer, opened devtools, then copied down the JWT value to use on their machine. 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). +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). #### A hybrid approach @@ -41,7 +41,7 @@ This comes with the benefit of not needing the additional database call for auth ### Authentication and TOP projects -For the purposes of TOP projects going forward, stick to stateful authentication using sessions. None of this means stateless authentication or JWTs are inherently bad, only that for the purposes of projects in this curriculum, it's not really worth the additional complexity trying to implement a more secure stateless solution when you can use a stateful one instead. "Scaling" is only relevant in context, and curriculum projects or even many small personal projects are seldom going to get to the point where stateful solutions will be a genuine performance bottleneck that requires a stateless solution instead. +For the purposes of TOP projects going forward, stick to stateful authentication using sessions. None of this means stateless authentication or JWTs are inherently bad, only that for the purposes of projects in this curriculum, it's not really worth the additional complexity trying to implement and ensure the security of stateless solution when you can use a stateful one instead. "Scaling" is only relevant in context, and curriculum projects or even many small personal projects are seldom going to get to the point where stateful solutions will be a genuine performance bottleneck that requires a stateless solution instead. There are plenty of good and bad implementations of authentication out in the wild, both stateful and stateless, hence it's good to be aware of the concepts and mechanisms. You may end up working with things in the future where stateless authentication (whether with JWTs or other types of tokens) makes perfect sense. As far as TOP projects are concerned though, that isn't quite the case; simply put, our use case for authenticating requests from an SPA and separate server is one where stateful sessions are a very appropriate solution, more so than stateless JWTs. From ac33332ea0894aa8b567bdd48821dbbbb76c62a0 Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Sun, 27 Jul 2025 17:32:56 +0100 Subject: [PATCH 19/24] Add section on third-party cookies --- .../authentication/session_management_in_practice.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/nodeJS/authentication/session_management_in_practice.md b/nodeJS/authentication/session_management_in_practice.md index 623f661dd55..9e29d03cb79 100644 --- a/nodeJS/authentication/session_management_in_practice.md +++ b/nodeJS/authentication/session_management_in_practice.md @@ -45,6 +45,16 @@ For the purposes of TOP projects going forward, stick to stateful authentication There are plenty of good and bad implementations of authentication out in the wild, both stateful and stateless, hence it's good to be aware of the concepts and mechanisms. You may end up working with things in the future where stateless authentication (whether with JWTs or other types of tokens) makes perfect sense. As far as TOP projects are concerned though, that isn't quite the case; simply put, our use case for authenticating requests from an SPA and separate server is one where stateful sessions are a very appropriate solution, more so than stateless JWTs. +### Cross-site authentication + +Given that we're recommending to stick with stateful sessions and the use of httpOnly cookies to send and store the session ID, there's a little more we have to do now that we're starting to make single page applications (SPAs) and hosting them separately from our servers. + +Earlier in the course, we made monolithic applications; the servers we made were also the ones serving the front end, meaning both ends would have been on the same domain when deployed. Any requests between client and server would have been "first party" (or "same site"). Browsers are very happy to set first-party cookies. + +The problem comes when each end is hosted on separate domains, where requests are "third party" (or "cross site"). Nowadays, browsers are not very happy to set third-party cookies, and you may have already heard about [restrictions or even blockages on third-party cookies across browsers](https://developer.mozilla.org/en-US/docs/Web/Privacy/Guides/Third-party_cookies#how_do_browsers_handle_third-party_cookies) over the last few years. This will pose a problem with our third-party session cookies! We'd send them from the server but the client won't set them, so no login persistence! + +We *could* handle this by purchasing a custom domain and setting things up so our separate client and server are both on that domain, meaning our session cookies would be first-party cookies, but that's out of the scope of this curriculum. So what can we do? + ### Assignment
From bf646cc834956b01dc2367d8b72a368941db759f Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Sun, 27 Jul 2025 18:21:54 +0100 Subject: [PATCH 20/24] Write section on reverse proxies --- .../session_management_in_practice.md | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/nodeJS/authentication/session_management_in_practice.md b/nodeJS/authentication/session_management_in_practice.md index 9e29d03cb79..637ad31de1d 100644 --- a/nodeJS/authentication/session_management_in_practice.md +++ b/nodeJS/authentication/session_management_in_practice.md @@ -55,6 +55,34 @@ The problem comes when each end is hosted on separate domains, where requests ar We *could* handle this by purchasing a custom domain and setting things up so our separate client and server are both on that domain, meaning our session cookies would be first-party cookies, but that's out of the scope of this curriculum. So what can we do? +#### Reverse proxies + +A reverse proxy is a server that takes requests from a client then forwards that request to another server, like a middleman, and is very versatile. This is one option for our third-party session cookie dilemma and the simplest to implement in terms of this curriculum's scope. + +The idea is that instead of sending requests directly to the main server, the client sends a request to the reverse proxy, which would be hosted on the same domain as the client. The reverse proxy would then forward that request to our main server. Our main server would then respond to the reverse proxy, which would then get forwarded back to the client. The important thing here is that the reverse proxy and client are hosted on the same domain, which would mean as far as the client is concerned, all cookie stuff is first party, not third party, and we know browsers are very happy setting first-party cookies. + +Fortunately for us, at the time of writing, both Netlify and Vercel allow us to set up reverse proxies on the same domain as the client without much work (unfortunately Cloudflare Pages does not support proxying to a different domain). Remember how with SPAs hosted on Netlify or Vercel, you'd need a "rewrite rule" to ensure all routes would still work if you refreshed the page or accessed them directly via the address bar? For example, Netlify would have required a `_redirects` file containing something like: + +```text +/* /index.html 200 +``` + +This would tell Netlify to "serve `index.html` for any route (not just `/`)", then React Router would take over as necessary once loaded. We can do something very similar to set up a reverse proxy. For example, using the same Netlify `_redirects` format, we can add another rewrite rule: + +```text +/api/* https://super-awesome-main-server-wow.com/:splat 200 +``` + +This would redirect any requests for a client-side endpoint beginning with `/api` (just an example - can be anything you want) to the equivalent endpoint on `https://super-awesome-main-server-wow.com`. + +So if your front end is hosted on `https://super-awesome-client-wow.netlify.app`. Instead of POSTing directly to `https://super-awesome-main-server-wow.com/sessions`, you would POST to `https://super-awesome-client-wow.netlify.app/api/sessions`. Since Netlify and Vercel both support reverse proxying to another domain, they would forward that request to `https://super-awesome-main-server-wow.com/sessions`. You would also need to [make sure your Express server can trust reverse proxies](https://expressjs.com/en/guide/behind-proxies.html) by adding something like this to your server setup: + +```javascript +app.set('trust proxy', 1); +``` + +In most cases, a value of 1 should suffice, though it's entirely possible that depending on where your server is hosted, a larger number is needed. Together, you can ensure a simpler and more secure stateful solution for session management while still having your client hosted on Netlify or Vercel, and your server hosted separately on one the [PaaS options from the Deployment lesson](https://www.theodinproject.com/lessons/node-path-nodejs-deployment#our-recommended-paas-services). + ### Assignment
From ff8f2d8cef86b8f9e9d2e51bf879606b9090b0c0 Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Sun, 27 Jul 2025 18:33:43 +0100 Subject: [PATCH 21/24] Add assignment/KC questions about reverse proxy with Netlify/Vercel --- nodeJS/authentication/session_management_in_practice.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nodeJS/authentication/session_management_in_practice.md b/nodeJS/authentication/session_management_in_practice.md index 637ad31de1d..36044593a88 100644 --- a/nodeJS/authentication/session_management_in_practice.md +++ b/nodeJS/authentication/session_management_in_practice.md @@ -89,6 +89,7 @@ In most cases, a value of 1 should suffice, though it's entirely possible that d 1. Read ["Stop using JWT for sessions"](http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/) for a breakdown of why the proposed benefits of JWTs (for essentially the same thing as sessions) may not be worth the complexities and potential vulnerabilities. 1. Read another take on [avoiding JWTs to implement browser sessions](https://ianlondon.github.io/posts/dont-use-jwts-for-sessions/). +1. Check out [Netlify's docs for proxying to another service](https://docs.netlify.com/manage/routing/redirects/rewrites-proxies/#proxy-to-another-service) as well as [Vercel's docs for proxying to another service](https://vercel.com/docs/rewrites#external-rewrites).
@@ -99,6 +100,8 @@ The following questions are an opportunity to reflect on key topics in this less - [Why might a product want to use stateless authentication instead of stateful?](#stateful-vs-stateless) - [What issues might one face with stale data in authentication tokens?](#authentication-and-authorization) - [What issues might stateless authentication have regarding invalidation?](#invalidation) +- [What issue can we face with session cookies when our client and server are hosted on separate domains?](#cross-site-authentication) +- [What is one way we can solve our third-party session cookie dilemma?](#reverse-proxies) ### Additional resources From 37d719059823f548f9288b373089921e475d6200 Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Sun, 27 Jul 2025 18:42:44 +0100 Subject: [PATCH 22/24] Streamline verbiage --- .../session_management_in_practice.md | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/nodeJS/authentication/session_management_in_practice.md b/nodeJS/authentication/session_management_in_practice.md index 36044593a88..dc6fb03a970 100644 --- a/nodeJS/authentication/session_management_in_practice.md +++ b/nodeJS/authentication/session_management_in_practice.md @@ -1,6 +1,8 @@ ### Introduction -In previous lessons, we covered both stateful authentication (demonstrated using server-side sessions) and stateless authentication (using JWTs) for the purpose of session management (persisting logins). You will often see both approaches out in the wild, although not necessarily implemented using sessions or JWTs specifically, but still, why the options? What are the pros and cons of each? How should you authenticate your applications? In this lesson, we will explore and compare our options specifically in the context of projects for the rest of this course, where authentication is used for session management. We will also touch on challenges you may face when it comes to authentication and deployment. +In previous lessons, we covered both stateful authentication (demonstrated using server-side sessions) and stateless authentication (using JWTs) for the purpose of session management (persisting logins). You will often see both approaches out in the wild, although not necessarily implemented using sessions or JWTs specifically, but still, why the options? What are the pros and cons of each? How should you authenticate your applications? + +In this lesson, we will explore and compare our options specifically in the context of projects for the rest of this course, where authentication is used for session management. We will also touch on challenges you may face when it comes to authentication and deployment. ### Lesson overview @@ -13,53 +15,53 @@ This section contains a general overview of topics that you will learn in this l 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? -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 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 become an issue, congratulations on the successful site!). +Stateless solutions reduce the number 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 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 become an issue, congratulations on the successful site!). -But is there actually a negative to using something like JWTs for stateless authentication? Yes, particularly when it comes to: **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**. #### Authentication and authorization -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. +Back in the JWT lesson, we demonstrated authenticating a request by verifying the JWT and 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 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. +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, then no matter who has the old session ID, there won't be a matching session, 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? -JWTs are much harder to invalidate. Say you generate one with a 2-day expiry and the client then logs out, deleting it from whatever storage medium was used. The client no longer has the token but since it's just text, anyone else who has that text could continue to use it and it would still be valid until expiry. The token could have been obtained via any number of malicious attack methods, including [cross-site scripting (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting) and [cross-site request forgery (CSRF)](https://en.wikipedia.org/wiki/Cross-site_request_forgery), especially if the token was stored somewhere like in local storage. At the most basic level, a pesky sibling/roommate could have gone on your computer, opened devtools, then copied down the JWT value to use on their machine. +JWTs are much harder to invalidate. Say you generate one with a 2-day expiry, then the client logs out, deleting it from whatever storage medium was used. The client no longer has the token, but since it's just text, anyone else who has that text could continue to use it and it would still be valid until expiry. The token could have been obtained via any number of malicious attack methods, including [cross-site scripting (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting) and [cross-site request forgery (CSRF)](https://en.wikipedia.org/wiki/Cross-site_request_forgery), especially if the token was stored somewhere like in local storage. At the most basic level, a pesky sibling/roommate could have gone on your computer, opened devtools, and then copied down the JWT value to use on their machine. -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! +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* 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). #### A hybrid approach -As a result, some services implement a hybrid stateful+stateless approach, such as using two tokens: "access" and "refresh". The main JWT is the "access token" and has a very short expiry. The client also receives a second "refresh token" with a much longer expiry, and *that* token is stored server-side (making it the stateful part). If the access token is still valid, it's used as normal. If it has expired, the server checks if the refresh token is valid. If it is, the server can generate a fresh access token for use, but if not, it can unauthorize the request. +As a result, some services implement a hybrid stateful/stateless approach, such as using two tokens: "access" and "refresh". The main JWT is the "access token" and has a very short expiry. The client also receives a second "refresh token" with a much longer expiry, and *that* token is stored server-side (making it the stateful part). If the access token is still valid, it's used as normal. If it has expired, the server checks if the refresh token is valid. If it is, the server can generate a fresh access token for use, but if not, it can unauthorize the request. This comes with the benefit of not needing the additional database call for authentication data for any requests made with a valid access token, and the long-expiry refresh token retains the longer login persistence for a better user experience. Since the refresh tokens can be invalidated by deleting them from the database, the short-expiry access token reduces the duration of potential vulnerability. ### Authentication and TOP projects -For the purposes of TOP projects going forward, stick to stateful authentication using sessions. None of this means stateless authentication or JWTs are inherently bad, only that for the purposes of projects in this curriculum, it's not really worth the additional complexity trying to implement and ensure the security of stateless solution when you can use a stateful one instead. "Scaling" is only relevant in context, and curriculum projects or even many small personal projects are seldom going to get to the point where stateful solutions will be a genuine performance bottleneck that requires a stateless solution instead. +For the purposes of TOP projects going forward, stick to stateful authentication using sessions. None of this means stateless authentication or JWTs are inherently bad, only that for the purposes of projects in this curriculum, it's not really worth the additional complexity trying to implement and ensure the security of a stateless solution when you can use a stateful one instead. "Scaling" is only relevant in context, and curriculum projects or even many small personal projects are seldom going to get to the point where stateful solutions will be a genuine performance bottleneck that requires a stateless solution instead. -There are plenty of good and bad implementations of authentication out in the wild, both stateful and stateless, hence it's good to be aware of the concepts and mechanisms. You may end up working with things in the future where stateless authentication (whether with JWTs or other types of tokens) makes perfect sense. As far as TOP projects are concerned though, that isn't quite the case; simply put, our use case for authenticating requests from an SPA and separate server is one where stateful sessions are a very appropriate solution, more so than stateless JWTs. +There are plenty of good and bad implementations of authentication out in the wild, both stateful and stateless; hence, it's good to be aware of the concepts and mechanisms. You may end up working with things in the future where stateless authentication (whether with JWTs or other types of tokens) makes perfect sense. As far as TOP projects are concerned though, that isn't quite the case; simply put, our use case for authenticating requests from an SPA and separate server is one where stateful sessions are a very appropriate solution, more so than stateless JWTs. ### Cross-site authentication -Given that we're recommending to stick with stateful sessions and the use of httpOnly cookies to send and store the session ID, there's a little more we have to do now that we're starting to make single page applications (SPAs) and hosting them separately from our servers. +Given that we're recommending sticking with stateful sessions and the use of httpOnly cookies to send and store the session ID, there's a little more we have to do now that we're starting to make single-page applications (SPAs) and hosting them separately from our servers. Earlier in the course, we made monolithic applications; the servers we made were also the ones serving the front end, meaning both ends would have been on the same domain when deployed. Any requests between client and server would have been "first party" (or "same site"). Browsers are very happy to set first-party cookies. -The problem comes when each end is hosted on separate domains, where requests are "third party" (or "cross site"). Nowadays, browsers are not very happy to set third-party cookies, and you may have already heard about [restrictions or even blockages on third-party cookies across browsers](https://developer.mozilla.org/en-US/docs/Web/Privacy/Guides/Third-party_cookies#how_do_browsers_handle_third-party_cookies) over the last few years. This will pose a problem with our third-party session cookies! We'd send them from the server but the client won't set them, so no login persistence! +The problem comes when each end is hosted on separate domains, where requests are "third party" (or "cross site"). Nowadays, browsers are not very happy to set third-party cookies, and you may have already heard about [restrictions on third-party cookies across browsers](https://developer.mozilla.org/en-US/docs/Web/Privacy/Guides/Third-party_cookies#how_do_browsers_handle_third-party_cookies) over the last few years. This will pose a problem with our third-party session cookies! We'd send them from the server, but the client won't set them, meaning no login persistence! -We *could* handle this by purchasing a custom domain and setting things up so our separate client and server are both on that domain, meaning our session cookies would be first-party cookies, but that's out of the scope of this curriculum. So what can we do? +We *could* handle this by purchasing a custom domain and setting things up so our separate client and server are both on that domain, meaning our session cookies would be first-party cookies, but that's out of the scope of this curriculum. So what can we do instead? #### Reverse proxies -A reverse proxy is a server that takes requests from a client then forwards that request to another server, like a middleman, and is very versatile. This is one option for our third-party session cookie dilemma and the simplest to implement in terms of this curriculum's scope. +A reverse proxy is a server that takes requests from a client and then forwards that request to another server, like a middleman. This versatile thing is one option for our third-party session cookie dilemma and the simplest to implement in terms of this curriculum's scope. -The idea is that instead of sending requests directly to the main server, the client sends a request to the reverse proxy, which would be hosted on the same domain as the client. The reverse proxy would then forward that request to our main server. Our main server would then respond to the reverse proxy, which would then get forwarded back to the client. The important thing here is that the reverse proxy and client are hosted on the same domain, which would mean as far as the client is concerned, all cookie stuff is first party, not third party, and we know browsers are very happy setting first-party cookies. +The idea is that instead of sending requests directly to the main server, the client sends a request to the reverse proxy, which would be hosted on the same domain as the client. The reverse proxy would then forward that request to our main server. Our main server would then respond to the reverse proxy, which would then forward the response back to the client. The important thing here is that the reverse proxy and client are hosted on the same domain, which would mean, as far as the client is concerned, everything is first party, not third party. This includes any cookies, and we know browsers are very happy setting first-party cookies. Fortunately for us, at the time of writing, both Netlify and Vercel allow us to set up reverse proxies on the same domain as the client without much work (unfortunately Cloudflare Pages does not support proxying to a different domain). Remember how with SPAs hosted on Netlify or Vercel, you'd need a "rewrite rule" to ensure all routes would still work if you refreshed the page or accessed them directly via the address bar? For example, Netlify would have required a `_redirects` file containing something like: @@ -78,10 +80,11 @@ This would redirect any requests for a client-side endpoint beginning with `/api So if your front end is hosted on `https://super-awesome-client-wow.netlify.app`. Instead of POSTing directly to `https://super-awesome-main-server-wow.com/sessions`, you would POST to `https://super-awesome-client-wow.netlify.app/api/sessions`. Since Netlify and Vercel both support reverse proxying to another domain, they would forward that request to `https://super-awesome-main-server-wow.com/sessions`. You would also need to [make sure your Express server can trust reverse proxies](https://expressjs.com/en/guide/behind-proxies.html) by adding something like this to your server setup: ```javascript +// somewhere early in app.js app.set('trust proxy', 1); ``` -In most cases, a value of 1 should suffice, though it's entirely possible that depending on where your server is hosted, a larger number is needed. Together, you can ensure a simpler and more secure stateful solution for session management while still having your client hosted on Netlify or Vercel, and your server hosted separately on one the [PaaS options from the Deployment lesson](https://www.theodinproject.com/lessons/node-path-nodejs-deployment#our-recommended-paas-services). +In most cases, a value of 1 should suffice, though it's entirely possible that, depending on where your server is hosted, a larger number is needed. Together, you can ensure a simpler and more secure stateful solution for session management while still having your client hosted on Netlify or Vercel and your server hosted separately on one of the [PaaS options from the Deployment lesson](https://www.theodinproject.com/lessons/node-path-nodejs-deployment#our-recommended-paas-services). ### Assignment From 547494a32cbdb92913e8d1304f3d33075d7ab307 Mon Sep 17 00:00:00 2001 From: mao-sz <122839503+mao-sz@users.noreply.github.com> Date: Sat, 13 Sep 2025 15:02:38 +0100 Subject: [PATCH 23/24] Remove cryto assignment Website served with HTTP (no HTTPS), and not strictly necessary given the other assigned resources. --- nodeJS/authentication/session_management_in_practice.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nodeJS/authentication/session_management_in_practice.md b/nodeJS/authentication/session_management_in_practice.md index dc6fb03a970..93d04e9e37b 100644 --- a/nodeJS/authentication/session_management_in_practice.md +++ b/nodeJS/authentication/session_management_in_practice.md @@ -90,8 +90,7 @@ In most cases, a value of 1 should suffice, though it's entirely possible that,
-1. Read ["Stop using JWT for sessions"](http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/) for a breakdown of why the proposed benefits of JWTs (for essentially the same thing as sessions) may not be worth the complexities and potential vulnerabilities. -1. Read another take on [avoiding JWTs to implement browser sessions](https://ianlondon.github.io/posts/dont-use-jwts-for-sessions/). +1. Read about [avoiding JWTs to implement browser sessions](https://ianlondon.github.io/posts/dont-use-jwts-for-sessions/). 1. Check out [Netlify's docs for proxying to another service](https://docs.netlify.com/manage/routing/redirects/rewrites-proxies/#proxy-to-another-service) as well as [Vercel's docs for proxying to another service](https://vercel.com/docs/rewrites#external-rewrites).
From b61d2b6744eb416cbbc9dae359707f93be92c09d Mon Sep 17 00:00:00 2001 From: mao-sz <122839503+mao-sz@users.noreply.github.com> Date: Mon, 17 Nov 2025 23:26:22 +0000 Subject: [PATCH 24/24] Rephrase LO items to be topic overviews than learning objectives Better matches style guide's intent for the section: https://github.com/TheOdinProject/curriculum/blob/main/LAYOUT_STYLE_GUIDE.md#lesson-layout --- nodeJS/authentication/session_management_in_practice.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nodeJS/authentication/session_management_in_practice.md b/nodeJS/authentication/session_management_in_practice.md index 93d04e9e37b..c0a58c58158 100644 --- a/nodeJS/authentication/session_management_in_practice.md +++ b/nodeJS/authentication/session_management_in_practice.md @@ -8,8 +8,8 @@ In this lesson, we will explore and compare our options specifically in the cont This section contains a general overview of topics that you will learn in this lesson. -- Compare pros and cons of stateful and stateless approaches to authentication and session management. -- Explore ways to handle authentication when the client and server are not hosted on the same domain. +- Comparison of stateful and stateless approaches to authentication and session management. +- Approaches to authentication when hosting on different domains. ### Stateful vs stateless