The Ultimate Guide to handling JWTs on frontend clients (GraphQL)
Tags: graphql, authentication, jwt
Published: 2019-09-23 08:44:25

---
title: The Ultimate Guide to handling JWTs on frontend clients (GraphQL)
published: true
description: JWTs are becoming a popular way of handling auth. This post aims to demystify what a JWT is, discuss its pros/cons and cover best practices in implementing JWT on the client-side, keeping security in mind. 
tags: GraphQL, Authentication, JWT
canonical_url: https://blog.hasura.io/best-practices-of-using-jwt-with-graphql/
---

> *This is an excerpt of an original post published on [blog.hasura.io](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql)*

JWTs (JSON Web Token, pronounced 'jot') are becoming a popular way of handling auth. This post aims to demystify what a JWT is, discuss its pros/cons and cover best practices in implementing JWT on the client-side, keeping security in mind. We’ve kept the examples especially relevant to GraphQL clients.


- [Introduction to JWT](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql#intro)
    - [Security considerations](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql#jwt_security)
    - [JWT structure](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql#jwt_structure)
    - [Why JWT instead of session tokens](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql#jwt_vs_session)
- [Login](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql#login)
    - [Persisting token or not?](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql#jwt_persist)
    - [Token usage on the client](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql#login_usage)
- [GraphQL client setup with JWT](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql#basics_client_setup)
    - [Dealing with token expiration](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql#basics_client_setup_expiration)
    - [Error handling](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql#basics_client_setup_expiration)
- [Logout](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql#logout)
    - [Token invalidation](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql#logout_token_invalidation)
    - [Blacklisting tokens](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql#logout_token_invalidation)
- [Silent refresh](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql#silent_refresh)
    - [How does a refresh token work?](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql#refresh_token)
    - [Where to store refresh token?](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql#refresh_token_persistance)
    - [Login flow with refresh tokens](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql#refresh_token_login)
    - [Refreshing when token expired](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql#refresh_token_expiry)
- [Persisting sessions](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql#persistance)
    - [Security considerations](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql#persistance_security)
    - [Error handling](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql#error_handling)
- [Force logout](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql#force_logout)
- [Server side rendering (SSR)](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql#ssr)




## Introduction: What is a JWT?

For a detailed, technical description of JWTs refer to this [article](https://jwt.io/introduction/).

For the purposes of auth, a JWT is a token that is issued by the server. The token has a JSON payload that contains information specific to the user. This token can be used by clients when talking to APIs (by sending it along as an HTTP header) so that the APIs can identify the user represented by the token, and take user specific action.

#### But can’t a client just create a random JSON payload an impersonate a user?

Good question! That’s why a JWT also contains a signature. This signature is created by the server that issued the token (let’s say your login endpoint) and any other server that receives this token can independently verify the signature to ensure that the JSON payload was not tampered with, and has information that was issued by a legitimate source.

#### But if I have a valid and signed JWT and someone steals it from the client, can’t they use my JWT forever?

Yes! If a JWT is stolen, then the thief can can keep using the JWT. An API that accepts JWTs does an independent verification without depending on the JWT source so the API server has no way of knowing if this was a stolen token! This is why JWTs have an expiry value. And these values are kept short. Common practice is to keep it around 15 minutes, so that any leaked JWTs will cease to be valid fairly quickly. But also, make sure that JWTs don’t get leaked.

> That’s why it’s also really important not to store JWT on the client, say via cookies  or localstorage. Doing so you make your app vulnerable to [CSRF](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)) & [XSS](https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)) attacks, by malicious forms or scripts to use or steal your token lying around in cookies or  localstorage.

#### So does a JWT have a specific kind of structure? What does it look like?

A JWT looks something like this, when it's *serialized*:

`eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.XbPfbIHMI6arZ3Y922BhjWgQzWXcXNrz0ogtVhfEd2o`

If you decode that base64, you'll get JSON in 3 important parts:  *header*, *payload* and *signature*.


![](https://blog.hasura.io/content/images/2019/08/Group.png)

The serialized form is in the following format:

`[ base64UrlEncode(header) ] . [ base64UrlEncode(payload) ] . [signature ]`

> A JWT is not encrypted. It is *based64* **encoded** and **signed**. So anyone can decode the token and use its data. A JWT's signature is used to verify that it is in fact from a legitimate source.

Here is the diagram of how a JWT is issued(`/login`) and then used to make an API call to another service(`/api`) in a nutshell:

![](https://blog.hasura.io/content/images/2019/08/Screen-Shot-2019-08-29-at-12.54.53.png)

#### Ugh! This seems complicated. Why shouldn’t I stick to good old session tokens?

This is a painful discussion on the Internet. Our short (and opinionated answer) is that backend developers like using JWTs because a) microservices b) not needing a centralized token database.

In a microservices setup, each microservice can independently verify that a token received from a client is valid. The microservice can further decode the token and extract relevant information without needing to have access to a centralized token database.

This is why API developers like JWTs, and we (on the client-side) need to figure out how to use it. However, if you can get away with a session token issued by your favorite monolithic framework, you’re totally good to go and probably don’t need JWTs!

[Continue reading here](https://blog.hasura.io/best-practices-of-using-jwt-with-graphql/#login)