Jwts Not Safe e Book
Jwts Not Safe e Book
© 2021 Redis
2
Table of Chapter 1:
HTTP Sessions, Authentication, and Authorization. . . . . . 3 Other considerations and issues . . . . . . . . . . . . . . . . . . . . . . . . 14
Contents The use case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 › Length of tokens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1. Where to store the session data (client vs. database). . . 4 › The state needs to be maintained anyway
2. How to send session data to the client. . . . . . . . . . . . . . . . . . . 5 (for rate-limiting, IP-whitelisting, etc.). . . . . . . . . . . . . . . . 14
3. How the client can send session tokens to the So why is JWT dangerous for user authentication?. . . . 15
server for future requests. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Still trying to make JWT work? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
4. How the server can handle authentication Bottom line. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
and authorization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 When can I use JWT?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
5. When will the session expire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 If I can’t use JWT, what else can I do?. . . . . . . . . . . . . . . . . . . . 17
Section summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Chapter 4:
Chapter 2: Storing Sessions in Redis. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Storing Sessions in a Traditional Database. . . . . . . . . . . . . . . . . 7 An example code snippet (Node.js). . . . . . . . . . . . . . . . . . . . . 19
The main problem with this approach:. . . . . . . . . . . . . . . . . . . . . . 8
There are two ways to solve this problem:. . . . . . . . . . . . . . 8 Chapter 5:
› Option 1: Eliminate database lookup (step four): . . . 8 Sessions When Redis Is Your Primary Database. . . . . . . . . 20
› Option 2: Make the database lookup so Is anyone using this architecture?. . . . . . . . . . . . . . . . . . . . . . . . 21
fast that the additional call won’t matter. . . . . . . . . . . . . 9
Chapter 6:
Chapter 3: Using Both Redis and JWT. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Storing Sessions in JWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 [1] References:. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Token expiration. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
JWT is too liberal for a security spec and About Redis. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
so is vulnerable. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
› The “none” algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
› The algorithms are passed in an array . . . . . . . . . . . . . . . 13
› Claims are optional. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
3
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
4
Introduction Below are some examples of SMEs talking about the security problems of JWT:
Source: “Why JWTs Are Bad for Authentication”— Source: “Stop using JWT for sessions”
Randall Degges, Head of Developer Advocacy, Okta, (see reference below for links).
a leading enterprise identity provider.
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
5
Introduction One of the main reasons for JWTs usage is the need for
speed. The other reason is that it’s simple to use. The last
reason is it’s a buzzworthy and friendly name that’s excellent
for marketing. The name combines “JSON” (which is
generally well liked), “Web” (for web), and “Token” (which
implies stateless), and all of this may make people think it’s
perfect for their web authentication. In reality, it’s not.
But it’s not all bad, because there are regular long and
passionate debates about JWT on Hacker News (see here,
here and here), so there is hope. This amount of debate
should give you pause because security should ideally be a
black-and-white issue: either something is secure or it’s not.
By the end of this book, you’ll know the benefits and the
dangers of JWTs, and also the battle-tested solution that
thousands of companies use to overcome this.
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
6
Chapter 1
HTTP Sessions, Authentication,
and Authorization
Before we get into JWTs, The use case
Imagine that you are using Twitter. You log in to the
let’s take a look at a use platform, you “like” someone’s tweet, and then you write
case to better understand a new tweet of your own. So you perform two additional
actions after you log in. You need to be authenticated and
sessions, authentication, authorized before you can perform each of the three spe-
and authorization. cific actions. This is because HTTP is a stateless protocol,
which means that the HTTP request doesn’t store who you
are from one request to the next.
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
7
Chapter 1 After you log in, the servers typically create a session. The session is a container that houses data about the
user’s interaction with the website or service, and, as its name implies, its lifetime is typically bound by the user’s
log in and log out actions. A session typically will have the following information:
• User’s profile information, such as name, date of birth, email address, etc.
• User’s permissions, such as “user,” “admin,” “supervisor,” “super-admin,” etc.
• Other app-related data, such as shopping cart details if it’s a retail app, etc.
• Session expiration, such as one hour from now, one week from now, etc.
Let’s look at each of these five points and get a general idea of how they work in most applications.
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
8
The session token is an opaque random string that looks something like this:
fsaf12312dfsdf364351312srw12312312dasd1et3423r
In the database, that string points to the entire session data. It will look something like this:
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
9
4. SEND COOKIE
CookieName: myAppCookie
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
10
Chapter 1 4. How the server can 5. When will the session expire
handle authentication Each session also has an expiration time, which can be
and authorization set by the backend developer as anything from 5 min-
utes to 30 days. After that set time, the session data will
be deleted. And if the user makes a call to perform some
Upon every future request, the server queries the data-
action, typically the user will be denied permission, and
base with the session token to get the actual session back,
most client applications will redirect the user to the login
and then the server checks for two things:
page, forcing them to log in again. And when they log in, a
new session is created with a new expiration time and the
1. You are authenticated: Your login data is still valid
cycle starts over.
(verifies it is not tampered with, not expired, not
logged out, etc.)
Note: If you authenticate using OAuth, you get multiple
2. You are authorized: You can log in but do you have
tokens such as “access token,” “refresh token,” and so on.
permission to do that specific action? (i.e., check if
These are all there to provide finer control of when the
you are an admin, data owner, user, employee, super
session should expire. For example, the client can use the
admin, etc.)
refresh token to extend the session for additional time
instead of logging people out.
Section summary
• HTTP is stateless, so to keep track of a user upon login, a “session” is created.
• A session is data about a user and their activity. It contains who they are, what they are authenticated and
authorized to do, and also to keep track of any specific product-related data.
• Session data is typically stored in a database.
• A “session token” that points to the session is created and sent to the client for future references.
• The client sends this “session token” for every future request (via request header or through a cookie) to
identify the user and other details that are stored in the session.
• The server retrieves the session from the session token by making an additional database call, checks if a valid
session exists, and if the session token and the session itself are valid, it lets the user take future actions, such
as liking a tweet, creating a tweet, etc.
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
11
Chapter 2
Storing Sessions in
a Traditional Database
You just learned how sessions work. Now, let’s continue with the Twitter example and see how the entire
process works when you log in to Twitter and submit a tweet.
Note: A session token is a long unidentifiable string—aka opaque string—that looks like this:
fsaf12312dfsdf364351312srw12312312dasd1et3423r
2. The server then sends you a session token to the frontend mobile or web application.
a. This token is then stored in the cookie or in the local storage of the app.
3. Next, say you write and submit a tweet. Along with your tweet, the app will then also send the session
token (through a cookie or a header) so that the server can identify who you are. (But remember that the
token is just a random string, so how can the server know who you are just from the session token?)
4. When the server receives the session token, it won’t know who the user is, so it sends that to the data-
base to retrieve the actual user’s info (such as the userID) from that token.
5. If the user exists and is allowed to complete that action (i.e., send a tweet), the server allows them to do
the action.
6. Finally, it tells the frontend that the tweet was sent.
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
12
Chapter 2
Send a Tweet
3. SESSION TOKEN +
4. SEND SESSION TOKEN
TWEET TEXT
6. TWEET SUCCESSFULLY
SAVED 4.A. SEND USER INFO
BROWSER SERVER TO SERVER
OR MOBILE DATABASE
APP
5. SAVE TWEET TO DB
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
13
Chapter 2 The main problem with Option 1: Eliminate database lookup (step four)
The main problem with this approach is that step four is 1. Store the state in the server’s memory. However, this
slow and needs to be repeated for every single action can cause issues when you scale since this state is only
the user does. So every API call leads to at least two slow available on a specific server.
DB calls, which can slow down the overall response time. 2. Use “sticky sessions.” This is when you instruct the
load balancer to always direct the traffic to a specific
There are two ways to solve this problem: server even after you scale up. Again, this can cause
1. Somehow eliminate database lookup for users different scaling issues and if the server goes down
completely (i.e., eliminate step four). (scale down), you’ll lose all the sessions.
2. Make the extra database lookup much faster so that 3. Use JSON Web Tokens. We’ll investigate how to do this
the additional hop won’t matter. in the following chapter.
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
14
Chapter 3
Storing Sessions in JWT
JWT, especially when used as a session, attempts the client and the server can see the user info part of
to solve the problem of time-consuming repeated the token, the second part, the signed part, can only be
database calls by completely eliminating the database verified by the server. In the example below, the pink
lookup altogether. section of the token contains the payload (user’s info) and
can be seen by both the client and the server.
The main idea is to store the user’s info in the session
token itself. This means, instead of some long, random But the blue part is signed using a secret string, the
string, the actual user info is passed in the session token header, and the payload itself. And so if the client tampers
itself. And to secure it, part of the token is signed using with the payload (say impersonates a different user), the
a secret that’s only known to the server. So even though signature will be different and won’t be authenticated.
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
15
Chapter 3 The previous image on page 14 shows a JWT token. It includes <header>.<payload>.<signature>. The header
(highlighted in red) and the payload (highlighted in purple) are often not encrypted (and just base64 encoded),
but the signature (highlighted in blue) is signed.
Going forward for every user action, the server simply verifies the signed section, gets the user info, and lets the
user complete that action, effectively skipping the DB call completely.
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
16
Chapter 3
3. JWT TOKEN +
TWEET TEXT
4. VERIFY IF THE JWT
TOKEN IS VALID, IF SO,
GET THE USER INFO
6. TWEET SUCCESSFULLY DIRECTLY FROM JWT
SAVED
BROWSER
OR MOBILE
APP SERVER 5. SAVE TWEET TO DB DATABASE
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
17
JWT is too “liberal” for a to avoid these loopholes. However, unlike with HTML, if
people don’t follow those best practices, it could cause a
security spec and therefore lot more damage than a bad rendering, such as allowing
weak authentication.
is vulnerable
The other problem is because the spec itself is so liberal,
The JWT specification is written more like the HTML JWT library creators don’t have a choice but to comply. For
specification. In HTML, if you don’t close an HTML tag (say that reason, backend engineers need to be very careful
a </div>), it’s still valid and the browsers continue to display when using JWT because what might be technically valid
it. The goal is to try to make the “best effort” to render according to the spec might not be secure.
something in the browser instead of throwing an error,
so it’s very “liberal” in that sense. But this causes a lot of On the next page are some examples
problems for browser developers and frontend engineers, of these potential security issues:
although thankfully the worst that can happen is just a bad
webpage rendering.
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
18
For example, say the attacker passes “alg” = none in the header. And say you are reading the alg from the request header
shown below (req.header.alg)—which is valid—you could then hit this vulnerability.
Client:
Server:
The solution to this problem is that the backend engineers need to ensure they ignore the “none” algorithm. Even Auth0,
which promotes JWT, got hit with a big security issue (read more about this here: Critical vulnerabilities in JSON Web
Token libraries [Auth0.com]).
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
19
The solution is to use just one algorithm, or use two different methods with just one algorithm each, and call two
methods independently.
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
20
2. The state needs to be maintained anyway (for rate-limiting, IP-whitelisting, etc.). In many real-world apps, servers
have to maintain the user’s IP and track APIs for rate-limiting and IP-whitelisting. So you’ll need to use a blazing-fast
database anyway. To think your app somehow becomes stateless with JWT is just not realistic.
Following are some use cases that could make this dangerous:
1. Logout doesn’t really log you out. Imagine you logged out from Twitter after sending your tweet. You’d think that you
are logged out of the server, but that’s not the case because JWT is self-contained and will continue to work until it
expires. This could be 5 minutes or 30 minutes or whatever the duration that’s set as part of the token. So if someone
gets access to that token during that time, they can continue to use it to authenticate until it expires.
2. Blocking users doesn’t immediately block them. Imagine you are a moderator of Twitter or some online real-time
game where real users are using the system. And as a moderator, you want to quickly block someone from abusing
the system. You can’t, again for the same reason. Even after you block them, the user will continue to have access to
the server until the token expires.
3. JWTs could contain stale data. Imagine the user is an admin and got demoted to a regular user with fewer permis-
sions. Again, this won’t take effect immediately and the user will continue to be an admin until the token expires.
4. JWT’s are often not encrypted. Because of this, anyone able to perform a man-in-the-middle attack and sniff the JWT
now has your authentication credentials. This is made easier because the MITM attack only needs to be completed on
the connection between the server and the client.
There are ways to encrypt JWT tokens called JWE, but when you use this method, the clients (especially browsers and
mobile devices) won’t have a way to decrypt them to see the actual payload. At this point, you are essentially using the
JWT as a regular encrypted session token—at least from the perspective of the web apps and mobile apps.
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
21
Figure 7. Source: Stop using SECURITY PROBLEM POINTLESS SECURITY PROBLEM USABILITY PROBLEM
JWT for sessions, part 2: Why
Once the attacker takes out Congratulations! You’ve Unlike cookies, which are If your user goes offline for just
your solution doesn’t work the server, he has free roam, reinvented sessions, with all protected from this, any a few minutes, they will have to
and there’s nothing you can do their problems (notably, their JavaScript on the page can login again when they return.
to stop him. need for centralized state), steal it. Including CDN scripts!
and gained nothing in the
process. But…
“But I can just change the signing key.” “I’ll just use refresh tokens.”
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
22
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
23
Chapter 4
Storing Sessions in Redis
If the answer to the problem we’ve outlined so far is to use What you need is a database that can serve millions of
the tried-and-true method (i.e., store the sessions in a data- requests in sub-milliseconds. Thousands of companies,
base), but to make that database lookup so fast that the ad- serving billions of users, use Redis for this exact purpose.
ditional call won’t matter, how exactly can this be achieved? With Redis, the additional database call is so fast that it no
longer presents a problem.
5. Save tweet to DB
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
24
And because Redis is so fast, you don’t need to send large user data back and forth between the client and server—just a
session token is enough. You can get the actual payload from Redis in micro-seconds or sub-milliseconds. Since you are
not sending the data to the client, it’s harder for people to steal. And since the actual data is inside Redis, you don’t have
to depend on session expiration time, you can just verify it against the Redis database itself. And finally, you can delete
the user data from Redis when they log out, so you can always be sure of authentication and authorization.
As you can see, it’s an age-old approach of storing the data in a database, but by making it blazing fast, you effectively
eliminate the speed issue. And it has no security vulnerabilities like JWT.
Since people have been using Redis for session storage for ages, there are plenty of examples of how to implement this in
virtually all languages and frameworks. But here is a simple overview of how to store data in sessions in NodeJS. It works the
same way in every language.
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
25
Source: https://github.com/tj/connect-redis
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
26
Chapter 4 2. Store whatever user information you want into the session and it will be stored in
Redis. The example below shows page view count (req.session.views++) being stored
as part of the session data. So every time this page is visited, the count will increase.
Source: https://github.com/expressjs/session#reqsession
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
27
Chapter 5
Sessions When Redis Is
Your Primary Database
Redis has been the leading database for caching and session storage for more than a decade now. But over the last
few years, Redis has evolved into a primary multi-model database that offers seven officially supported modules. For
example, you can use RedisJSON (10X faster vs. the market leader) and essentially have a real-time MongoDB-like
database, or use the RediSearch module (4X to 100X faster) and implement real-time full-text search like Algolia.
With Redis as your primary database, everything becomes blazing fast—not just your session storage. In this architecture, all
the application’s primary data and the sessions data—as well as everything else—lives side-by-side in the same database.
Send a Tweet
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
28
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
29
Learn more about how you can use Redis as a primary database by watching these videos:
• Redis in 100 seconds [2021, 200,000+ views]
• Redis as a Primary DB (Ofer Bengal, CEO, Redis)
• Redis as a Primary DB(Yiftach Shoolman, CTO, Redis)
• Goodbye cache, Redis as a primary DB
• What is DBLess architecture? [2021]
• Can Redis be used as a Primary DB? [2021]
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
30
Chapter 6
Using Both Redis and JWT
In this final chapter we will review another widely used One last thing to note here is that, as mentioned above,
option that provides some of the benefits of JWT but this setup will still make the app vulnerable to potential
removes most of the security issues previously discussed man-in-the-middle attacks between the clients and server
(with the exception of man-in-the-middle attacks). It is because the tokens are not encrypted.
possible to use JWT as a preliminary check while using
Redis as the secondary check. In such a scenario, if the As mentioned earlier, there is a way to encrypt JWT tokens
JWT verification succeeds, the server will still go to Redis called JWE, but when you use this method, the clients
and double-check the information there. However, if the (especially browsers and mobile devices) won’t have a way
JWT verification itself fails, there’s no need to worry about to decrypt them to see the actual payload. At this point,
checking the Redis database. you are essentially using the JWT as a regular encrypted
session token, at least from the perspective of the web
Another benefit of this approach is that you get to use apps and mobile apps.
existing JWT libraries on both the frontend and backend
without having to develop your own custom way of stor- If you are using it for machine-to-machine communica-
ing the data in Redis (although it’s not a big deal). tion, such as with microservices when you want to share
login info between two different services, you can then
share public keys to decrypt and see the JWT data—but
that’s a different use case.
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
31
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
32
Chapter 6 In the following example, we will use Redis as the primary DB,
but the process is the same even if you have an additional DB.
Send a Tweet
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
33
Redis E-Book / JSON Web Tokens (JWTs) Are Not Safe © 2021 Redis
About Redis