In this post, I will try to explain what is JWT, what are its advantages and why you should be using it.
JWT stands for JSON Web Tokens. Let me explain what each word means.
A JWT looks like a random sequence of strings separated by 2 dots. The yyyyy part which you see below has the Base64 encoded form of json data mentioned earlier.
xxxxx.yyyyy.zzzzz
The 3 parts in order are -
Header - Header is the base64 encoded json which contains hashing algorithm on which the token is secured.
Payload - Payload is the base64 encoded json data which needs to be shared through the token.
The json can include some default keys like iss (issuer), exp (expiration time), sub (subject) etc. Particularly exp here is the interesting one as it allows specifying expiry time of the token.
At this point you might be thinking that how is JWT secure if all we are doing is base64 encoding payload. After all, there are easy ways to decode base64. This is where the 3rd part (zzzzz) is used.
secret. The secret should be kept confidential to the ownerHMACSHA256(
xxxxx + "." + yyyyy,
secret)
Once you realize it, the idea of JWT is quite simple. To use JWT for authentication, what you do is you make the client POST their username and password to a certain url.
If the combination is correct, you return a JWT including username in the "Payload". So the payload looks like -
{
"username": "john.doe"
}
Once the client has this JWT, they can send the same in Header when accessing protected routes. The server can read the JWT from the header and verify its correctness by matching the signature (zzzzz part) with the encoded hash created using header+payload and secret (generated signature).
If the strings match, it means that the JWT is valid and therefore the request can be given access to the routes.
BTW, you won't have to go through such a deal for using JWT for authentication, there are already a handful of libraries that can do these for you.
For using JWT in Python, we can use the pyjwt library.
For the data, it can take any dictionary object.
import jwt
encoded = jwt.encode({'some': 'payload'}, 'secret', algorithm='HS256')
print(encoded)
# xxxx.yyyy.zzzz
jwt.decode(encoded, 'secret', algorithms=['HS256'])
# returns back the dictionary
As you might have noticed in the previous section, JWT has a payload field that can contain any type of information.
If you include username in it, you will be able to identify the user just by validating the JWT and there will be no need to read from the database unlike typical tokens which require a database read cycle to get the claimed user.
Now if you go ahead and include permission informations in JWT too (like 'isAdmin': True), then more database reads can be prevented.
And this optimization comes at no cost at all. So this is why you should be using JWT.
That's it for now. Thanks for reading. 🙌🏻