In this article we will learn the fundamentals of a JWT token is and how we can benefit from it for authenticating communications between two parties, all of this using vanilla NodeJS and javascript.
JWT is an abbreviation for JSON Web Token, which is a compact URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is digitally signed using JSON Web Signature (JWS). ~ IETF
Urggh! What?
Simply put, JWT token is a string we pass in the header or url while making a network request to pass data safely and make sure it hasn't been tampered with.
Example: www.example.com/private/?token=xxxxx.yyyyy.zzzzz
You might be wondering what's with the token format! JWT tokens consists of three parts separated by dots
( . )
which are:
header.payload.signature
Let's see the differents parts of a JWT token in details.
1. Header
The header typically consists of two parts: the type of the token, which is JWT, and the hashing algorithm being used, such as HMAC SHA256 or RSA.
{
"alg": "HS256",
"typ": "JWT"
}
Then, this JSON is Base64Url encoded to form the first part of the JWT.
'use strict';
var header = { "alg": "HS256", "typ": "JWT" };
var enc_header = Buffer.from(JSON.stringify(header)).toString('base64');
// โบ "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"
2. Payload
The second part of the token is the payload, which contains the claims. Claims are predefined keys and their values. There are three types of claims: registered, public, and private claims.
Registered claims: These are a set of predefined keys which are not mandatory but recommended. Some of them are iss (issuer), exp (expiration time) etc.
Public claims: These can be defined at will by those using JWTs. But to avoid collisions they should be defined in the IANA JSON Web Token Registry or be defined as a URI that contains a collision resistant namespace.
Private claims: These are the custom key value pairs created to share information between parties that agree on using them and are neither registered or public claims.
{
"exp": "2019-02-14",
"message": "roses are red"
}
The payload is then Base64Url encoded to form the second part of the JSON Web Token.
'use strict';
var payload = { "exp": "2019-02-14", "message": "roses are red" };
var enc_payload = Buffer.from(JSON.stringify(payload)).toString('base64');
// โบ eyJleHAiOiIyMDE5LTAyLTE0IiwibmFtZSI6IkpvaG4gRG9lIn0
3. Signature
To create the signature part you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that. Too good for us that NodeJS comes with the immensely powerful Crypto library out of the box which we will use in our example.
'use strict';
const crypto = require('crypto');
var jwt_secret = "secret";
// enc_header and enc_payload are computed earlier
var signature = crypto.createHmac('sha256', jwt_secret).update(enc_header +"."+ enc_payload).digest('base64');
// โบ 6C46KAaZGp6RjbSqGllfdQF7g8vXCp02NTSrz-PzeoI
The signature is used to verify that the sender of the JWT is who it says it is and to ensure that the message wasn't changed along the way.
The final JWT token looks like this
var token = `${enc_header}.${enc_payload}.${signature}`;
// โบ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIyMDE5LTAyLTE0IiwibWVzc2FnZSI6InJvc2VzIGFyZSByZWQifQ.0u-mkgLo5479CPjJJ4mXCwn2RW4dFT12fiYiopRWsZw
Something important to remember here is that JWT tokens are used for authentication and not encryption, so even without knowing the secret key, someone can read your header and payload data.
But upon receiving the token you can sign the header and payload again with your secret key and compare it with the received signature to detect tampering of token or the message.
A good place to start will be by going to this online JWT debugger at jwt.io and play around with the the token we just generated above.
Hi! I'm @Siwalik! If you liked this article, follow me on twitter to know about my latest tech expeditions and side projects! ๐
Top comments (11)
Can you explain me:
Hi @nemanja_pet!
You can use JWT token for various types of authentications, even for logged in users. For example when a user logs in to your website with their credentials, the api response might return a JWT token as a part of the response. After logging in, on subsequent calls to the API, the client (browser) can send the JWT token to the server and on authenticating the token, the API can return results to make sure it's a legit request.
You can definitely store a JWT token in the client in cookies, local / session storage based on your need. Just make sure to not generate the JWT token in the client as the secret will be visible on inspecting source.
Ideally you should! The payload part can contain a claim called "exp" whose value should be a timestamp when the token expires. That way the same token cannot be highjacked by someone else and used to make API calls impersonating the actual user.
Hope that answers your questions.
You might find my article on using JWTs for client authentication useful.
Great article @perrydbucs ๐
JWTs are simply an authentication mechanism, and can be used as part of your method of authentication in various ways. My company uses JWTs for one of our web services (REST API), with a keystore holding the public certificates of trusted clients which can then request a temporary access token. Since we're using RS256 instead of HMAC256, we have the capability to not only private communication between the client and server but also guarantee that this person is who they say they are, since the key to decrypt their JWS has to be in our public keystore already. To conclude:
For us, the JWT isn't created when the user logs on, but in order to log on. We use JWTs as an assertion of user authentication, generating a temporary access token where we set expiration time and the system they get access to, and return that JWT as the response.
A REST API won't use cookies, the client that made the request will have to handle maintaining it themselves, but that's one way of doing it. It just needs to be stored on the client side. But make sure to keep it safe, it's effectively a plaintext password if it doesn't contain any context-specific data within the body (which in turn is verified by the JWS).
How we manage this has been described, but to spell it out: Yes. A JWT token has an expiration property for a reason. If it is being used as an access token, an indefinite JWT can be as dangerous as a password. As an example, we have a protocol for client and server. Clients assertion token should have a lifetime of up to 5 minutes, and the server will return an access token with a lifetime of an hour. Any subsequent requests to the access service and you will have to request a new one by creating a new JWT to be used as the assertion token.
Let me know if you have any other questions about this! I tried (hah) to keep it short but it got fairly lengthy anyway.
Really concise explanation, thanks!
Thank you!
I agree, thanks for a great contribution.
From the man himself ๐! Thanks Ben.
Keep up the great work!
Some comments may only be visible to logged-in visitors. Sign in to view all comments.