The reason why JWT-s are used is to prove that the sent data was actually created by an authentic source.
This means the client will get this token which is signed somehow with a secret (stay tuned) and with that the server can trust that client that it is already authenticated without having to handle sessions in memory.
It's very important to mention that the purpose is not to hide data! Let me show you this through an example.
Autopsy of a token
I would like to give a try for another approach by explaining how JWT-s work and it is by using an existing example and analysing it.
Let's have a token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJleGFtcGxlLmNvbSIsInN1YiI6ImFkbWluIiwiZ3JwIjpbImFkbWluIiwidXNlcnMiXSwiYWRtaW4iOnRydWUsImF1ZCI6ImV4YW1wbGUiLCJleHAiOjE1MTQ3NjQ4MDAsImlhdCI6MTQ5OTI2NDQ4NX0.w1Ls_fdotl3SdqFp2GcadSzc8a5Po77qeIUgknZ0X78
Separate them by the character "." and we have three parts.
The first one is the "Header". It is encoded via Base64, which you can decode via your browser for example.
Try it in your console: atob("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9")
This is going to return {"alg":"HS256","typ":"JWT"} , which stands for
- typ: the type of the token which is JWT
- alg: the hash algorithm which is going to produce a signature for the header and the payload
The key part here is that this is not even signed, you can read it anytime! You just need to decode the Base64 string via e.g. your browser or however you would like to.
The middle part is the Payload. Similarly you can decode it by calling
atob("eyJpc3MiOiJleGFtcGxlLmNvbSIsInN1YiI6ImFkbWluIiwiZ3JwIjpbImFkbWluIiwidXNlcnMiXSwiYWRtaW4iOnRydWUsImF1ZCI6ImV4YW1wbGUiLCJleHAiOjE1MTQ3NjQ4MDAsImlhdCI6MTQ5OTI2NDQ4NX0")
which stands for:
{"iss":"example.com","sub":"admin","grp":["admin","users"],"admin":true,"aud":"example","exp":1514764800,"iat":1499264485}
BOOM! Nothing fancy, just decoding some Base64 string, that's it!
These keys are mainly standing for who you are and when this token will be expired, but you can check out more here: https://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#rfc.section.4.1.6
The last part is the signature itself. NOW comes the interesting part.
The plan is the following how we can create a signature:
- First you need a secret which is a string. In our case it is "That's a secret."
- Then you'll need to Base64 encode your Header and Payload (remember, these are JSON strings!) - let's call them B64Header and B64Payload from now on.
- After that you can sign these by passing two arguments for the chosen hashing algorithm (HS256 in this case)
- The first argument is a string which looks like this: B64Header + "." + B64Payload
- The second argument is the secret.
- And the hashing algorithm returns then the signiture, which is going to be the last part of the token. Easy!
To make sure you understood everything visit https://jwt.io/ and try the token I provided in this article and make sure it's signed correctly (so it is a valid signature!)
Cheers!