3 Ways to Invalidate a Jwt Token in the Backend Side

The JWT is the most used way to authenticate a request to a backend server.

Still, what happens when I want to log out the user? As the token not stored on the backend server, I can’t remove it. The validity date of the JWT still valid.

Here are 3 solutions I’ve used to handle this situation.

JWT Authentication

I use the JWT to authenticate the frontend request against a backend. I use this mechanism mainly in stateless applications, to avoid having a session and a cookie.

This way, the authentication system is independent of the backend. Once generated the JWT, the backend has no more to do with it but sending the JWT to the frontend.

The user information can be stored in the JWT. An expiration date can also be stored in the JWT to avoid having the JWT useable forever.

Fine. But the log out is another situation.

The Log Out

As the application is stateless, when the user requests a log out, the backend has nothing to do. In fact, the backend can do nothing.

As the JWT is stored in the frontend, it’s the frontend which must delete the JWT.

But what if the frontend doesn’t delete it? The JWT still valid and can be used with the requests.

The backend must do something to avoid this.

List The Invalid JWTs

One solution can be to list in a table all the JWT that are no more accepted.

I can create a table like this:

create table invalid_token(
    token text,
    expiration_date date
);

In this table I store the tokens used to log out. I also store the expiration date present in the JWT. This way, in a batch process, I can easily delete the rows where the JWT is expired.

In the following snippet, I show an example in Python of the logout endpoint.

@route("/logout", methods=["POST"])
def logout():
    access_token = request.user.access_token
    payload = jwt.decode(access_token, SECRET_KEY, algorithms="HS256")
    expiration_date = payload["exp"]
    InvalidToken(access_token, expiration_date).save()
    return Response(status=204)

I must also adapt the verification of the JWT of a request like this:

def verify_token(token):
    invalid_token = InvalidToken.query.filter(token=token).one_or_none()
    if invalid_token:
        raise Exception("Invalid token used")
    payload = jwt.decode(token, SECRET_KEY, algorithms="HS256")
    user = User.query.filter(id=payload["sub"]).one_or_none()
    return user

List The Generated JWTs

I can also do the reverse. I can store all the generated JWTs in a table.

And when the logout endpoint is called, remove from the list the JWTs of the current user.

Here is an example of the table:

create table valid_token(
    token text,
    app_user_id references app_user(id)
);

I add a reference to the user, to let delete all the tokens related to a single user.

Here is an example of the logout endpoint in Python:

@route("/logout", methods=["POST"])
def logout():
    user_id = request.user.id
    ValidToken.query\
        .filter(user_id=user_id).delete()
    return Response(status=204)

An alternative is to delete only the token used in the request. This makes a different between a logout and a logout from all devices.

The verification of the token must also be done against the new table:

def verify_token(token):
    valid_token = ValidToken.query\
        .filter(token=token).one_or_none()
    if not valid_token:
        raise Exception("Unknown token used")
    payload = jwt.decode(token, SECRET_KEY, algorithms="HS256")
    user = User.query.filter(id=payload["sub"]).one_or_none()
    return user

User Login status

The last solution I’ve used is to store the login situation of the user. If the backend knows that the user is logged or not, I trust all the JWT from this user.

Nevertheless, with this implementation I can’t make the difference between the logout and the logout from all the devices.

Those implementations are based on the following solution in Stackoverflow.

If you want to learn more about good quality code, make sure to follow me on Youtube.


Never Miss Another Tech Innovation

Concrete insights and actionable resources delivered straight to your inbox to boost your developer career.

My New ebook, Best Practices To Create A Backend With Spring Boot 3, is available now.

Best practices to create a backend with Spring Boot 3

One response to “3 Ways to Invalidate a Jwt Token in the Backend Side”

  1. […] fact, it’s not easy, but it’s possible. Check this article for more […]

    Like

Leave a comment

Discover more from The Dev World - Sergio Lema

Subscribe now to keep reading and get access to the full archive.

Continue reading