Skip to content

Commit 1e3053a

Browse files
committed
feat: latest lesson content improvments
1 parent ca6d833 commit 1e3053a

File tree

8 files changed

+113
-28
lines changed

8 files changed

+113
-28
lines changed

public/images/banner.png

15.1 KB
Loading

views/demo/home.ejs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/kognise/water.css@latest/dist/dark.min.css">
2-
<h2>✓ You've been successfully authenticated!</h2>
3-
<p style="width:70%;"><br/><br/>
2+
<strong>✓ You've been successfully authenticated!</strong>
3+
<h2>Method 1: Send JWT in request parameters</h2>
4+
<p style="width:70%;">
45
In this request, we sent token via request URI parameter<br/>
5-
GET /demo/protected-endpoint?<b>access_token</b>=mF_9.B5f-4.1JqM HTTP/1.1<br/><br/>
6+
<code>GET /demo/protected-endpoint?<b>access_token</b>=mF_9.B5f-4.1JqM HTTP/1.1</code><br/><br/>
67
> <a href="https://tools.ietf.org/html/rfc6750#section-2.3" target="_blank">Read about standards to follow while sending token via URI Query Parameter</a><br/><br/>
78
Let's learn about more secure ways to send the token to the authorization server.<br/>
89
</p>
9-
<form method="POST" action="/demo/protected/web-form" enctype="application\/x-www-form-urlencoded"><input name="access_token" type="hidden" value="<%= token %>" /><input type="submit" value="Click to send token in form body"></input></form>
10+
<h2>Method 2: Send JWT in form body</h2>
1011
<p>
1112
> Input Parameter Name: access_token<br/>
1213
> Content-Type: application/x-www-form-urlencoded<br/>
13-
> <a href="https://tools.ietf.org/html/rfc6750#section-2.2" target="_blank">Read about standards to send token via form-encoded body parameters</a>
14+
<form method="POST" action="/demo/protected/web-form" enctype="application\/x-www-form-urlencoded"><input name="access_token" type="hidden" value="<%= token %>" /><input type="submit" value="Click to send token in form body"></input></form>
15+
<br/>
1416
</p>
1517

1618
<br/><br/><br/><br/><br/><br/>

views/demo/tokenInBody.ejs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/kognise/water.css@latest/dist/dark.min.css">
2-
<h2>✓ You've been successfully authenticated!</h2>
3-
<p style="width:70%;"><br/><br/>
2+
<strong>✓ You've been successfully authenticated!</strong>
3+
<p style="width:70%;">
44
In this request, we sent the token in the form body<br/>
55
> <a href="https://tools.ietf.org/html/rfc6750#section-2.2" target="_blank">Read about standards to send token via form-encoded body parameters</a><br/><br/>
66
There are other ways to send token to authorization server as well.
77
Next, lets's explore
88
</p>
9-
<a id="apiReqBtn" href="#!" onclick="javasctipt:requestProtectedAPI()">Send token in request header now</a>
9+
<h2>Method 3: Send JWT in request header</h2>
10+
<button><a id="apiReqBtn" href="#!" onclick="javasctipt:requestProtectedAPI()">Click to send token in request header</a></button>
1011
<small id="apiReqResponse" style="font-weight:bold;background-color:grey;color:#ffffff;margin-left:16px;"></small><br/><br/>
1112
<script>function requestProtectedAPI(){
1213
console.log("Going to request API")
@@ -45,7 +46,8 @@ Pragma: no-cache
4546
> <a href="https://tools.ietf.org/html/rfc6750#section-2.1" target="_blank" style="opacity:0.7;">Read about standards to send token via request headers</a>
4647
<br/><br/><br/><br/>
4748
<b>And there are more ways to send token to authorization server</b><br/>
48-
<a href="/lesson/jwt-in-web-cookies">Next: Sending token in cookies</a><br/><br/>
49+
<h2>Method 4: Send JWT in cookies</h2>
50+
<a href="/lesson/jwt-in-web-cookies">Next: Send JWT in cookies</a><br/><br/>
4951

5052
<br/><br/><br/><br/><br/><br/>
5153
<footer>

views/home.ejs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,25 @@
11
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/kognise/water.css@latest/dist/dark.min.css">
22
<h1>JWT Authentication Demo</h1>
3+
<h3>Learn JWT by reverse engineering & debugging</h3>
4+
<img src="/images/banner.png" style="width: 100%;height: auto;" />
5+
36
<br/><br/>
4-
This is a tutorial with live demo to show how jwt authentication can be implemented using node.js, express, jsonwebtoken.
7+
<p>This is an interactive tutorial to learn about JWT by reverse engineering. By the end of this tutorial, you’ll learn what a JWT is and how you can implement authentication using JWTs in your app.
58
<br/>We'll start with examples and then reverse engineer by deconstructing each part.
6-
<br/><br/>
9+
</p>
10+
<p>
11+
<strong>Prior Knowledge Expected</strong><br/>
12+
I am expecting you to have a very high-level overview of following concepts but I will also make sure to link necessary learning resources wherever you need them
13+
<ul>
14+
<li>HTML forms and cookies</li>
15+
<li>HTTP web requests</li>
16+
<li>Public-key cryptography (no need to learn the math, just learn what it does)</li>
17+
<li>Base64 encoding (no need to learn the math)</li>
18+
</ul>
19+
</p>
20+
<strong>Time Required: 15 mins</strong>
721

22+
<br/><br/>
823
<details>
924
<summary>Topics Covered</summary>
1025
<div>
@@ -21,7 +36,7 @@ This is a tutorial with live demo to show how jwt authentication can be implemen
2136
</details>
2237

2338
<br/><br/>
24-
<a href="/jwt">Next: Create JWT token</a>
39+
<a href="/jwt">Next: How does a JWT look like?</a>
2540
<br/><br/><br/><br/><br/><br/>
2641

2742
<footer>

views/jwt/create/success.ejs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,22 @@
1212
</ul>
1313
> <a href="https://tools.ietf.org/html/rfc7520#section-4.1.2" target="_blank" style="opacity:0.7;">Read about the signing operation</a>
1414
<br/><br/>
15-
<a target="_blank" href="/verify/<%= token %>">Server can verify this token</a>
15+
<a target="_blank" href="/jwt/verify/<%= token %>">Server can verify this token</a>
1616
with secret key(for HMAC algorithm) or the public key(for RSA algorithm)<br/>
1717
<br/><br/>
18-
<h3>Let's put the token to some use now</h3>
19-
<a href="/demo/protected?access_token=<%= token %>">Next: Access resource protected with this token</a>
18+
<h3>Let's put this token to some use now</h3>
19+
<p style="font-weight: 300;">
20+
We created this example token to be used to authenticate a user. Let’s send this token to a backend server which holds private files of users.
21+
<br/>There are 4 ways you can send JWT to backend
22+
<ol>
23+
<li>In request parameters</li>
24+
<li>In a form body</li>
25+
<li>In request headers</li>
26+
<li>In cookies</li>
27+
</ol>
28+
</p>
29+
30+
<a href="/demo/protected?access_token=<%= token %>">Next: Send JWT in request parameters</a>
2031
<br/><br/><br/><br/>
2132
<a href="/jwt/form" style="opacity:0.7;">Create a new token with different algorithm</a><br/><br/>
2233
<a href="/">Go Home</a><br/>

views/jwt/index.ejs

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,79 @@
66
<span id="token-part-payload" style="color:blue;"><%= token.split(".")[1] %></span><span style="font-weight:bold;font-size:120%;">.</span>
77
<span id="token-part-signature" style="color:green;"><%= token.split(".")[2] %></span>
88
</div>
9-
<br/><br/>
9+
<br/>
10+
<p>
11+
This is a practical example of a JWT
12+
<br/>Wow, it looks garbage!
13+
<br/>Sure it does look like garbage, but it is not. In the next few minutes, you’ll see how easy it is to turn this garbage into useful information.
14+
</p>
1015
<h3>Token schema</h3>
1116
<p>Did you notice two dots(.) in the token? These dots (.) separate 3 important parts of the token</p>
1217

1318
<b><code>{<span style="color:red;">header</span>}.{<span style="color:blue;">payload</span>}.{<span style="color:green;">signature</span>}</code></b><br/>
1419
<ol>
15-
<li><b>Header</b>: Metadata about the cryptography methods e.g. Algorithm, Token type.
16-
<br/>Encoded with base64UrlEncode, can easily be decoded by anyone who has access to token.
17-
<br/><span>Let's <a href="javascript:alert(window.atob(document.getElementById('token-part-header').textContent))">decode header</a> with browser's <code>atob()</code> method</span>
20+
<li><b>Header</b><code style="color: red; font-size: 80%;margin-left: 12px;">eyJhbGciOiJSU....</code>
21+
<br/>This part is the metadata about the cryptography methods used for signature(the last part of this token)
22+
e.g. The Cryptography Algorithm, Token type, etc.
23+
<p style="font-weight: 300;">
24+
<span style="font-weight: 200;opacity: 80%;">What! Where? It is not readable.</span>
25+
<br/>Hold on! The header is encoded with <code>base64UrlEncode</code>, and can easily be decoded by anyone without any additional information other than the token itself. Let's decode this header with browser's <code>atob()</code> method.
26+
<br/><br/><button><a href="javascript:alert(window.atob(document.getElementById('token-part-header').textContent))">Click to decode header</a></button>
27+
<br/>(This will show you the decoded header in plain text)
28+
29+
<br/><br/>👉 Takeaway: The header can be decoded by anyone. It’s not garbage for anyone.
30+
</p>
31+
</li>
32+
<li><b>Payload</b><code style="color: blue; font-size: 80%;margin-left: 12px;">eyJkYXRhIjoiSSB....</code>
33+
<br/>Actual data we want to exchange via this token e.g. userId
34+
<p style="font-weight: 300;">
35+
This is also encoded with <code>base64UrlEncode</code>. Just like the header, let's decode payload as well with browser’s <code>atob</code> method.
36+
<br/><br/><button><a href="javascript:alert(window.atob(document.getElementById('token-part-payload').textContent))">Click to decode payload</a></button>
37+
<br/>This will show you the decoded payload in plain text
38+
<br/><br/>👉 Takeaway: The payload can be decoded by anyone. It’s not garbage for anyone.
39+
</p>
1840
</li>
19-
<li><b>Payload</b>: Actual data we want to exchange e.g. userId.
20-
<br/>This is also encoded with base64UrlEncode. <span>Let's <a href="javascript:alert(window.atob(document.getElementById('token-part-payload').textContent))">decode payload</a></span>
41+
<li><b>Signature</b><code style="color: green; font-size: 80%;margin-left: 12px;">RmT_mo6_TjjTiuv....</code>
42+
<br/>To verify sender or ensure message integrity
43+
<p style="font-weight: 300;">
44+
Can be verified by anyone if they know a secret/publicKey. But changing data(spoofing) is not possible.
45+
<br/><br/><span style="font-weight: 200;">What do you need to verify a token's integrity?</span>
46+
<br/>You need something more than just the token. You need to know a public key corresponding to the private-key used during the creation of this token.
47+
<br/><br/>Because I am the creator of this example token that I just showed you. I used an algorithm called <code>RSA256</code> where I used a pair of public/private keys for this token.
48+
<br/>Now, I’m sharing the public key with you, now you go ahead and verify JWT integrity with this public key.
49+
<br/><br/><button><a target="_blank" href="/jwt/verify/<%= token %>">Verify this JWT now</a> </button>
50+
</p>
2151
</li>
22-
<li><b>Signature</b>: To verify sender or ensure message integrity. Can be verified by anyone if they know secret/publicKey. But changing data(spoofing) is not possible.</li>
2352
</ol>
2453

54+
<br/>Ok, now you understand how does a JWT look like, but...
55+
<h2>What can JWTs be used for?</h2>
56+
<p style="font-weight: 300;">
57+
JWTs can be used as a digital claim issued by one party, which another party can verify for integrity.
58+
<ul>
59+
<li>Typical usage of JWTs are</li>
60+
<li>To prove whether a user is logged in or not</li>
61+
<li>To prove whether a user is authorized to perform admin actions or not</li>
62+
</ul>
63+
What’s more interesting?
64+
<strong>In order to verify JWT integrity, the other party(one that verifies) does not need to communicate with the first party(one that created JWT)</strong>. Well, assuming the first party has shared the public key with the other party already.
65+
<br/>So what if I leverage this to create a system as following
66+
<ol>
67+
<li>A computer verifies user identity(e.g. username/password) and issues JWTs to the users. Let’s call it an “identity server”</li>
68+
<li>Another computer that takes requests for users’ protected resources, let’s call it “application server”. It asks for JWT along with the request. This computer(application server) verifies the JWT and makes sure that the JWT was not tampered with</li>
69+
<li>And then the above “application server” uses JWT payload data to decide whether to give access to a particular resource or not. Essentially allowing the access to users as “identity server” wanted (remember the identity server created the JWT in step 1, at that time, it had also put in the access related necessary info in the JWT)</li>
70+
</ol>
71+
72+
This is a typical example of authentication/authorization using JWTs and the interesting thing here is that you separated the work related to identity vs work related to actual user resources. You don’t need to rely on a single central system any more to effectively do this and thus can scale and manage in a better way.
73+
</p>
74+
75+
Let’s see this system in action
76+
2577

26-
<a target="_blank" href="https://jwt.io/introduction/">Read more..</a><br/>
78+
<!-- <a target="_blank" href="https://jwt.io/introduction/">Read more..</a><br/> -->
2779

2880
<br/><br/>
29-
<a href="/jwt/verify/<%= token %>">Next: Verify JWT.</a><br/>
81+
<a href="/jwt/form">Next: Create a JWT</a><br/>
3082

3183
<br/><br/><br/><br/><br/><br/>
3284
<footer>

views/lesson/jwtCookies.ejs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/kognise/water.css@latest/dist/dark.min.css">
2-
<h2>Lesson : Authentication workflow for web using cookies as token store</h2>
2+
<h2>Method 4: Send JWT in cookies</h2>
3+
In this lesson, we will demo a typical authentication workflow for web using cookies as token store
4+
<br/><br/>
35
<a href="#!" onclick="openSignInWindow('/demo/authorize','login')">1. Login to get the token</a>
46
<script>
57
let windowObjectReference = null;
@@ -71,9 +73,9 @@ function requestProtectedAPI(){
7173
3. <a href="/demo/user" style="opacity:0.7;">User data link accessible via token in authorization header with fall back to cookies</a>
7274
<br/><br/>
7375
4. <a href="/demo/logout">Logout</a>
74-
<br/><br/><br/><br/>
75-
<a href="https://tools.ietf.org/html/rfc6265" target="_blank" style="opacity:0.7;">Read about securely storing cookies</a>
7676
<br/><br/>
77+
🔗 <a href="https://tools.ietf.org/html/rfc6265" target="_blank" style="opacity:0.7;">Read about securely storing cookies</a>
78+
<br/><br/><br/><br/>
7779
<a href="/lesson/token-transmit-method-comparison">Next: Choosing best method to send tokens to auth server</a>
7880
<br/><br/><br/><br/>
7981

views/lesson/transitMethodComparison.ejs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/kognise/water.css@latest/dist/dark.min.css">
22
<h2>So, which method is the best to send tokens to authorization server?</h2>
33
<br/>
4-
<p>
4+
<p style="font-weight: 300;">
55
For APIs, the recommended approach is to send token in authorization header as per Oauth RFC (Bearer Token).<br/>
66
For web, it's debatable how to send and store the token, considering the possible attacks(e.g. XSS, CSRF, etc.) vs Performance.<br/>
77
<br/>
88
<b>So now, we can generate token, we can send it to server to access the protected resource, verify if the token is valid.<br/> But how do we implement logout?</b><br/>
99
</p>
10+
<br/>
1011
<a href="/lesson/implementing-logout">Next: Implementing logout</a><br/><br/>
1112

1213
<br/><br/><br/><br/><br/><br/>

0 commit comments

Comments
 (0)