From 617aaf593fc3aa50d0ffec360c0213c6e046e1d0 Mon Sep 17 00:00:00 2001
From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com>
Date: Sat, 10 May 2025 19:34:03 +0100
Subject: [PATCH 04/20] Set up minimal app example code
---
nodeJS/authentication/json_web_tokens.md | 44 ++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/nodeJS/authentication/json_web_tokens.md b/nodeJS/authentication/json_web_tokens.md
index 873d83a9800..a02d5d13929 100644
--- a/nodeJS/authentication/json_web_tokens.md
+++ b/nodeJS/authentication/json_web_tokens.md
@@ -34,6 +34,50 @@ We can use JWTs to authenticate our APIs in a stateless manner, that is the serv
This is not all sunshine and roses, however. There are always tradeoffs, especially when security is concerned, and we will discuss these in more detail in a later lesson where we compare stateful authentication with sessions and stateless authentication with JWTs. Nonetheless, you're likely to encounter this sort of authentication at some point out in the wild, so it's good to get some experience with the concept (even if a basic implementation).
+#### Setup
+
+Like with the Sessions lesson, make a new database within `psql` with a `users` table:
+
+```sql
+CREATE TABLE users (
+ id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
+ username VARCHAR ( 255 ),
+ password VARCHAR ( 255 )
+);
+```
+
+Again, we will make a very minimal Express app. Since we've just been learning about REST APIs, we won't be using EJS views but responding with JSON from our endpoints. Since we won't be making a website for this, you should [download Postman](https://www.postman.com/downloads/) and use that to send requests to the API.
+
+```bash
+npm install express dotenv pg jsonwebtoken
+```
+
+```javascript
+// app.js
+require("dotenv").config();
+const { Pool } = require("pg");
+const express = require("express");
+
+const pool = new Pool({
+ // add your db configuration
+});
+
+const app = express();
+
+app.use(express.urlencoded({ extended: false }));
+
+app.get("/me", (req, res) => {
+ res.status(401).json("You are not logged in!");
+});
+
+const PORT = process.env.PORT || 3000;
+app.listen(PORT, () => {
+ console.log(`App listening on port ${PORT}!`);
+});
+```
+
+Since we're going to use stateless authentication, the server does not need to store the authentication data itself and so our setup code is a little simpler this time round. Run your server with `node app.js` and test it works by using Postman to send a GET request to `/me` at the appropriate localhost port, e.g. `http://localhost:3000/me`. You should get back a 401 with the string `"You are not logged in!"`.
+
### Assignment
From 1aed4b3bc12145c16baf8286ea95b0deacc44953 Mon Sep 17 00:00:00 2001
From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com>
Date: Sun, 11 May 2025 13:54:46 +0100
Subject: [PATCH 05/20] Change tutorial setup to example snippet
No need for a full handholdy tutorial. Just highlight the differences
between stateful/stateless and session/JWT
---
nodeJS/authentication/json_web_tokens.md | 58 +++++++++---------------
1 file changed, 22 insertions(+), 36 deletions(-)
diff --git a/nodeJS/authentication/json_web_tokens.md b/nodeJS/authentication/json_web_tokens.md
index a02d5d13929..8886a8e31ba 100644
--- a/nodeJS/authentication/json_web_tokens.md
+++ b/nodeJS/authentication/json_web_tokens.md
@@ -2,7 +2,7 @@
Previously, we learned about using sessions to persist logins and authenticate users. Session data would be stored server-side and the client issued their session's ID via a cookie. When authenticating, the session store would be checked for a matching session. This kind of authentication is "stateful".
-An alternative approach to authentication, and one that is common with REST APIs, is to use "stateless" authentication with JSON web tokens (JWTs). The main difference between using stateful and stateless authentication is where the authentication data is stored: client-side or server-side. In this lesson, you will be introduced to stateless authentication using JWTs.
+An alternative approach to authentication, and one that is common with REST APIs, is to use "stateless" authentication with JSON web tokens (JWTs). The main difference between using stateful and stateless authentication is where the authentication data is stored: server-side or client-side. In this lesson, you will be introduced to stateless authentication using JWTs.
### Lesson overview
@@ -34,49 +34,35 @@ We can use JWTs to authenticate our APIs in a stateless manner, that is the serv
This is not all sunshine and roses, however. There are always tradeoffs, especially when security is concerned, and we will discuss these in more detail in a later lesson where we compare stateful authentication with sessions and stateless authentication with JWTs. Nonetheless, you're likely to encounter this sort of authentication at some point out in the wild, so it's good to get some experience with the concept (even if a basic implementation).
-#### Setup
+### Generating JWTs
-Like with the Sessions lesson, make a new database within `psql` with a `users` table:
-
-```sql
-CREATE TABLE users (
- id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
- username VARCHAR ( 255 ),
- password VARCHAR ( 255 )
-);
-```
-
-Again, we will make a very minimal Express app. Since we've just been learning about REST APIs, we won't be using EJS views but responding with JSON from our endpoints. Since we won't be making a website for this, you should [download Postman](https://www.postman.com/downloads/) and use that to send requests to the API.
-
-```bash
-npm install express dotenv pg jsonwebtoken
-```
+Back in the sessions lesson, when a user successfully logged in, their ID was serialised to a session which was saved to the database, and a cookie sent back to the client with the signed session ID. With JWTs, a very similar process occurs, just a JWT is created and sent instead, and nothing gets saved to the database. You can generate JWTs using the [jsonwebtoken](https://www.npmjs.com/package/jsonwebtoken) library. For example, in a login route middleware:
```javascript
-// app.js
-require("dotenv").config();
-const { Pool } = require("pg");
-const express = require("express");
-
-const pool = new Pool({
- // add your db configuration
-});
+// importing the jsonwebtoken library somewhere appropriate
+const jwt = require("jsonwebtoken");
+
+// somewhere in a login route middleware
+if (user?.password === req.body.password) {
+ const token = jwt.sign({
+ id: user.id
+ }, process.env.SECRET, { expiresIn: "1d" });
+
+ res.set({Authorization: `Bearer ${token}`}).json("Login successful");
+} else {
+ res.status(401).json("Incorrect username or password");
+}
+```
-const app = express();
+There are many ways JWTs can be sent to and from servers, such as in the response's "Authorization" header via the [Bearer scheme](https://security.stackexchange.com/questions/108662) or via httpOnly cookies. Since we have not yet covered how to handle cross-site cookies, the example above sends the JWT as a bearer token in the response's Authorization header.
-app.use(express.urlencoded({ extended: false }));
+
-app.get("/me", (req, res) => {
- res.status(401).json("You are not logged in!");
-});
+#### JWT payloads and sensitive data
-const PORT = process.env.PORT || 3000;
-app.listen(PORT, () => {
- console.log(`App listening on port ${PORT}!`);
-});
-```
+Remember that JWTs are sent to and stored on the client. If a malicious party is able to access the token at any point, they can read its contents. While you should not need to do so anyway, **do not store sensitive data in a JWT.**
-Since we're going to use stateless authentication, the server does not need to store the authentication data itself and so our setup code is a little simpler this time round. Run your server with `node app.js` and test it works by using Postman to send a GET request to `/me` at the appropriate localhost port, e.g. `http://localhost:3000/me`. You should get back a 401 with the string `"You are not logged in!"`.
+
### Assignment
From 2f9008f91967a543dab718b49c7ae66f4dd67506 Mon Sep 17 00:00:00 2001
From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com>
Date: Sun, 11 May 2025 15:07:18 +0100
Subject: [PATCH 06/20] Write example of JWT verification middleware
---
nodeJS/authentication/json_web_tokens.md | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/nodeJS/authentication/json_web_tokens.md b/nodeJS/authentication/json_web_tokens.md
index 8886a8e31ba..02662d85600 100644
--- a/nodeJS/authentication/json_web_tokens.md
+++ b/nodeJS/authentication/json_web_tokens.md
@@ -2,7 +2,7 @@
Previously, we learned about using sessions to persist logins and authenticate users. Session data would be stored server-side and the client issued their session's ID via a cookie. When authenticating, the session store would be checked for a matching session. This kind of authentication is "stateful".
-An alternative approach to authentication, and one that is common with REST APIs, is to use "stateless" authentication with JSON web tokens (JWTs). The main difference between using stateful and stateless authentication is where the authentication data is stored: server-side or client-side. In this lesson, you will be introduced to stateless authentication using JWTs.
+An alternative approach to authentication, and one that is common with REST APIs, is to use "stateless" authentication with JSON web tokens (JWTs). While many of the overarching auth concepts and processes remain the same, the main difference between using stateful and stateless authentication is where the authentication data is stored: server-side or client-side. In this lesson, you will be introduced to stateless authentication using JWTs.
### Lesson overview
@@ -36,7 +36,7 @@ This is not all sunshine and roses, however. There are always tradeoffs, especia
### Generating JWTs
-Back in the sessions lesson, when a user successfully logged in, their ID was serialised to a session which was saved to the database, and a cookie sent back to the client with the signed session ID. With JWTs, a very similar process occurs, just a JWT is created and sent instead, and nothing gets saved to the database. You can generate JWTs using the [jsonwebtoken](https://www.npmjs.com/package/jsonwebtoken) library. For example, in a login route middleware:
+Back in the Sessions lesson, when a user successfully logged in, their ID was serialised to a session which was saved to the database, and a cookie sent back to the client with the signed session ID. With JWTs, a very similar process occurs, just a JWT is created and sent instead, and nothing gets saved to the database. You can generate JWTs using the [jsonwebtoken](https://www.npmjs.com/package/jsonwebtoken) library. For example, in a login route middleware:
```javascript
// importing the jsonwebtoken library somewhere appropriate
@@ -64,6 +64,25 @@ Remember that JWTs are sent to and stored on the client. If a malicious party is
+### Verifying JWTs
+
+So when a user successfully logs in, the server generates and sends a signed JWT in response. What about for incoming requests to routes we want to protect?
+
+The client must attach the JWT to any such requests, whether that's through `fetch` in a script or when using something like Postman. In our case, we'll do the same as earlier and write to the "Authorization" header using the format `Bearer: