Why you should not use JWT for authentication (2024)

JWT (JSON Web Token) is a well-known and simple method of authenticating a user. Almost all tutorials you did on the backend, specially API building tutorials probably told you to use JWT. I also thought once that JWT is the modern and better authentication method. Of course, it was a lack of my knowledge. This article tries to shed some light on this and show you some other alternatives of JWT, which can be better suited depending on your needs

What is JWT?

JWT (JSON Web Token) is a stateless token containing user information, signed using public-private cryptography. As such, an intruder cannot modify the token information, because that would also change the signature.

A JWT token looks like this

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

This example is taken from jwt.io. You will find the decoded version if you visit the page. It contains sub (user identification), name and iat (issuing time). Instead of iat, exp (expiry time) is also used.

This image can help you understand the breakdown

Why you should not use JWT for authentication (1)

Advantages of JWT

Stateless: It is stateless. So no data needs to be persisted to authenticate any user

Self-contained data: You don't need any other source of truth to verify your user. Claims allow you to add extra data params, like if the user is admin.

Disadvantages of JWT

Client-controlled logout

With JWT, the biggest problem is there are no reliable ways to log out users. The logout is fully controlled by the client, the server side can do nothing about it. It can just expect the client will forget about the token, that's it. This is dangerous from a security perspective.

You can, of course, use short-lived tokens and use refresh tokens to fetch new JWT tokens. Let's say, your token expiration time is 2 mins. Now, you have to handle the complexity of using refresh tokens and generating new tokens every 2 minutes. This will be a big overhead in your front end. It will also cost your servers if your application grows large. Above all, you still don't have full control if you want to unauthenticate a user.

Blacklisting user sessions

Maybe some logins got marked as unauthorized by the user, maybe the login was suspicious, or the device is lost or not used anymore. In that case, you would want to blacklist that token. To do this, you would actually have to store those blacklisted tokens in a persistent database and check through them each time a user needs authorized access. This can be an overhead. Besides, storing blacklisted tokens is equivalent to maintaining state on the server, which somewhat defeats the purpose of JWT.

Manually adding it to requests

You have to add the JWT in each of your request headers manually or have some config in place to do that for you.

Storage security

Many devs use localStorage to store session tokens, which can be easily exploited through JavaScript XSS (Cross-site scripting) attacks. You can, however, store the token in secure cookies. But that would solve only one problem

So, what is the solution?

The solution: Good old session cookies

Session cookies are underrated. They are old but gold.

This is how it works: when a user logs in with the correct credentials, the server creates a random bearer token representing the session and sends the session back as a cookie.

user_idsession_tokenexpiry
247a0479900504cb3ab4a1f626d174d2d1516239022
20050479900504cb3ab4a1f626d171f621516239822
50504cb39900504cb3ab4a1f626d171f61556239822

The user id 2 is logged in with two different devices, thus two sessions. The session_token, which is random and unpredictable, will be sent as cookies.

Does managing it seem complex? Not really. Popular web frameworks have some abstraction in place to handle cookie-based sessions. In this article, we will see how we can use Flask to handle session cookies.

Advantages of session cookies

Server-controlled logout

Whenever a user needs to log out, the server can just delete the session entry, and that's it. The user gets logged out immediately, totally controlled by the server. This is a more reliable solution compared to JWT.

Blacklisting

This is also easy. Why keep a list of blacklisted sessions when you can just delete them? If a user marks his device as lost, you can delete all the sessions of that user, forcing him to log in again with his credentials.

Auto-attachment

With how cookies work in general, you don't have to add the cookie with each of the request headers. Once the web browser receives a cookie, it will send the cookie automatically with each of the subsequent requests. These cookies are secure and cannot be accessed or modified using JavaScript.

Disadvantages of session cookies

Increased database read/write

Sessions are persisted in DB. This might result in a slightly increased load on scaling. But in real-world systems, Redis is used to store user sessions, which solves this issue.

CSRF Attack

If not taken preventive measures, session cookies are vulnerable to Cross-site request forgery. To solve this issue in a dynamic website, CSRF tokens can be used. As for REST APIs, CORS (Cross-origin resource sharing) can be configured properly to prevent unwanted requests.

Implementing a REST-like API with Flask and session cookies

I will demonstrate a simple example with Flask to use session cookies. We will use Flask-Login, which will manage the session cookies for us.

First, we will create a User model and some mock database methods

# user.pyfrom flask_login import UserMixinclass User(UserMixin): def __init__(self, id: int, name: str, email: str, password: str): self.id = id self.name = name self.email = email self.password = password # in a real application, password would be hashed def get_id(self): # required by flask_login return str(self.id)# Mock DBu1 = User(1, 'TestUser', '[email protected]', 'weakpassword')u2 = User(2, 'SecondUser', '[email protected]', 'pass2')users = [u1, u2]def get_user(id): for user in users: if user.id == id: return user return None

The UserMixin model implements some methods that are required by Flask-Login. This get_user will act as a fake database method.

Next, we need to instantiate LoginManager() . We will use a separate file for this:

# login_manager.pyfrom flask_login import LoginManagerfrom user import get_userlogin_manager = LoginManager()@login_manager.user_loaderdef load_user(user_id): # in a real application, you would fetch the user from DB _id = int(user_id) return get_user(_id)@login_manager.unauthorized_handlerdef unauthorized(): return {'message': 'Unauthorized'}, 401

The load_user method will be used by Flask-Login to reload a user. How the user is returned is totally up to you. In our case, we will be returning the user from our mock DB. In a real application, you would fetch the user using your ORM (SQLAlchemy, in most cases).

Finally, the main.py file will be used to include the routes and start the server.

# main.pyfrom flask import Flask, requestfrom flask_login import login_user, logout_user, login_required, current_userfrom user import get_userfrom login_manager import login_managerapp = Flask(__name__)app.config['SECRET_KEY'] = 'some-nice-secret-key'login_manager.init_app(app)@app.route('/heartbeat', methods=['GET'])def heartbeat(): return {'status': 'OK'}@app.route('/login', methods=['POST'])def login(): data = request.get_json() user = get_user(data['user_id']) if not user: return {'message': 'User not found'}, 400 if user.email == data['email'] and user.password == data['password']: login_user(user) else: return {'message': 'Invalid credentials'}, 400 return {'message': 'User logged in'}@app.route('/logout', methods=['POST'])@login_requireddef logout(): logout_user() return {'message': 'Logged out'}@app.route('/profile/<user_id>', methods=['GET'])@login_requireddef profile(user_id): user = get_user(int(user_id)) if not user or current_user.id != user.id: return login_manager.unauthorized() return {'name': user.name, 'email': user.email}app.run(host='0.0.0.0', port=81)

The login and logout methods are self-explanatory. Notice that the logout method doesn't take any kind of user-identifying param. Just calling logout_user will automatically fetch the session cookie attached to the request, and log the user out.

To access certain profile data, you have to be logged in as that user.

That's it! The full code can be accessed and run from this Repl (Click Show Files to see the code).

Where to use JWT?

Don't get me wrong, JWT is a solid solution, but it works best in certain scenarios, not all. In a gateway backend (backend directly communicating with web client), JWT complicates things. Besides server implementation, you have to maintain a whole lot of logic in the front end. On the other hand, cookies make everything simpler.

Although JWT might not always be the solution for your web API authentications, it definitely has some use of its own. It's a great way to gain temporary access to protected 3rd party resources. Or in another terms, JWT is best suited when communicating API to API.

Suppose, you use Spotify. Now, for the sake of this example, let's say a song is stored in AWS S3 and the access URL looks like this

https://s3.spotify.com/music/example-music.mp3?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Notice the token param with the query. The token param has a JWT, which verifies that you're an authenticated user of Spotify and can access the music file for the next X minutes. Usually, file access is not directly related to your Web API in this case, so, a stateless token can be super useful to give privileged access to files.

The following diagram can help you understand this

Why you should not use JWT for authentication (2)

In the above example, Gateway API uses session cookies, and the related services are under a private network. But, S3 Access is separate from your business logic and thus it shouldn't know anything about your application. As such, a JWT token is the best approach to give controlled access to your S3 files (like the music files in Spotify in our example).

Thanks for reading this far. I hope this article clarified the concepts. If you liked it, please share it with your network. If you have any feedback or questions, drop them in the comments. Thanks again!

Why you should not use JWT for authentication (2024)
Top Articles
Ballantyne West - Charlotte, NC
Apples of the Earth | St. Luke's Health | St. Luke's Health
Regal Amc Near Me
Frank Lloyd Wright, born 150 years ago, still fascinates
Asian Feels Login
New Slayer Boss - The Araxyte
St Als Elm Clinic
Yi Asian Chinese Union
Kris Carolla Obituary
Citi Card Thomas Rhett Presale
Bill Devane Obituary
Housing Intranet Unt
Love Compatibility Test / Calculator by Horoscope | MyAstrology
ATV Blue Book - Values & Used Prices
Nonuclub
The most iconic acting lineages in cinema history
24 Best Things To Do in Great Yarmouth Norfolk
ARK: Survival Evolved Valguero Map Guide: Resource Locations, Bosses, & Dinos
Walmart stores in 6 states no longer provide single-use bags at checkout: Which states are next?
Free Online Games on CrazyGames | Play Now!
Wgu Academy Phone Number
Closest Bj Near Me
1989 Chevy Caprice For Sale Craigslist
Vegito Clothes Xenoverse 2
Babbychula
Soulstone Survivors Igg
Hood County Buy Sell And Trade
Galaxy Fold 4 im Test: Kauftipp trotz Nachfolger?
Mandy Rose - WWE News, Rumors, & Updates
Kirsten Hatfield Crime Junkie
Gilchrist Verband - Lumedis - Ihre Schulterspezialisten
Timeline of the September 11 Attacks
Danielle Ranslow Obituary
Remnants of Filth: Yuwu (Novel) Vol. 4
Cinema | Düsseldorfer Filmkunstkinos
Astro Seek Asteroid Chart
Vistatech Quadcopter Drone With Camera Reviews
Serenity Of Lathrop - Manteca Photos
October 31St Weather
Manatee County Recorder Of Deeds
450 Miles Away From Me
COVID-19/Coronavirus Assistance Programs | FindHelp.org
Divinity: Original Sin II - How to Use the Conjurer Class
Silicone Spray Advance Auto
Ehome America Coupon Code
CrossFit 101
Big Brother 23: Wiki, Vote, Cast, Release Date, Contestants, Winner, Elimination
Diccionario De Los Sueños Misabueso
Game Like Tales Of Androgyny
Spongebob Meme Pic
Tamilyogi Cc
Latest Posts
Article information

Author: Clemencia Bogisich Ret

Last Updated:

Views: 6598

Rating: 5 / 5 (80 voted)

Reviews: 87% of readers found this page helpful

Author information

Name: Clemencia Bogisich Ret

Birthday: 2001-07-17

Address: Suite 794 53887 Geri Spring, West Cristentown, KY 54855

Phone: +5934435460663

Job: Central Hospitality Director

Hobby: Yoga, Electronics, Rafting, Lockpicking, Inline skating, Puzzles, scrapbook

Introduction: My name is Clemencia Bogisich Ret, I am a super, outstanding, graceful, friendly, vast, comfortable, agreeable person who loves writing and wants to share my knowledge and understanding with you.