Open-Source Internship opportunity by OpenGenus for programmers. Apply now.
In this article, we are going to cover a detailed explanation of JWT. Why do we use it? How we will make it work. We will be also covering the best practices of using JWT.
Table Of Contents:
- What is JWT?
- The problem we are solving with JWT
- Working principles of JWT
- Basic structure
- Best practices to follow
- Alternatives of JWT
What is JWT ?
JSON Web Token (JWT) or as many call it "Jot". Authentication, authorization and in some cases some even use it for Stateless Session management. However, to put it simply, this JWT is most commonly used to secure API endpoints.
JWT usually shares security information between the two parties. These two parties are the client and the server.
The problem we are solving with JWT
First, let's see where I see the problem or which problem I want to fix with JWT. A common use case is this - let's say there is so much load on my server that the user faces problems in login and signup. Or I want that even if there is any problem in my resource server, my users do not face any problems to login and signup.
So I want to create a separate auth server (assuming one server will do both authentication & authorization) which will validate the identity of a user with user credentials. After confirming the user identity it will also define what permissions he will have. Now my frontend and backend server, before sharing a resource, how it will know that the identity of the user, requesting to access the resource has been verified? And whether he has the appropriate permission to access this resource? Because the work of authentication and authorization has been done on another separate auth server.
Working principles of JWT
In this case, the client, auth server, and frontend/backend servers can share information among themselves using “Token”. This process can be done by following a few steps below.
- We will verify the username and password after receiving it from the client's browser.
- Then if verified, we will generate an encrypted token from my auth server which will be signed with a secret key. This secret key is also known by the application server.
- Then the token will be sent to the client. This token may contain the user role and some user information. An expiration time of the token is also set.
- The client will then send the token along with the request to any endpoint of my application server.
- Since the frontend/backend server has the secret key, it can easily understand by validating the token, that the identity of the client from whom the request came has already been verified.
- It also checks the expiration time of the token. If expired, the token is rejected.
- The application server decrypts the token and responds accordingly with the user role and the required information.
The login with a third party that we use, also follows such procedures. Tokens are often used for a very short time. For example, when downloading a resource that is stored on an external server, a token is given from auth server which will be verified by the external server, and only then it will give resource access.
The token I have mentioned so far, JWT is a token like that.
Basic structure
Let's consider a scenario. You are an admin of a public blog. When someone writes a blog it receives a pending status. The admin reviews the blog and publish it.The API endpoint that publishes the blog requires a verifaction of that, the request has came from an admin. We can verify this by retrieving user data from database.But this is expensive, right? JWT is here to help us.From the auth server, after the validation of your identity you will be given a role "admin" by fetching database only once. Let's see how the whole process works:
A JWT is made up of three parts: Header,Payload, and Signature.Therefore, a JWT typically looks like the following.
encoded(header).encoded(payload).signed(encoded(header),encoded(payload), secret_key)
-
Header - It is a JSON object containing encryption algorithm, and token type.The best is to choose between these two algorithms - HS256 (HMAC using SHA256), or RS256 (RSA using SHA256). This JSON is then Base64Url encoded.
{ "alg": "HS256", "typ": "JWT" }
-
Payload - It will contain iss (issuer, who issued you the token) , exp (expiration time), sub (subject, based on your use-case), role, and other informations you want to integrate in payload.
{ "username": "cinmoy98", "iss":"https://auth_server.com/", "exp": 153452683 "role": "admin" }
-
Signature - This is made up of encoded header and payload and then encrypted with a SECRET_KEY.
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), SECRET_KEY)
The signature is used to ensure that the jwt hasn't been changed along way, and in the case of jwt signed with a private key, it can also ensure that the sender of the JWT is who they claim to be.
The token will be like this.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImNpbm1veTk4IiwiaXNzIjoiaHR0cHM6Ly9hdXRoX3NlcnZlci5jb20vIiwiZXhwIjoxNTM0NTI2ODMsInJvbGUiOiJhZG1pbiJ9.7233Vcpaad0WwInO1RSTG6GJ5VEwv2Rz2R_0cH-Ui1s
When you as an admin will request to publish the post along with the JWT token,the backend server will check if you have the admin role from the decrypted token.It will also check the expiration time.If all goes ok, your request will be executed.
You should send the JWT, typically in the Authorization header using the Bearer schema. The header should contain the following information:
Authorization: Bearer <jwt-token>
Best practices to follow
However, to use this JWT you need to follow some standard practice, otherwise, its use will make the security of your system vulnerable.
-
First, JWT can be considered like money. The central bank prints money by putting some security features in the money by which we can verify whether the money is real or fake. But when I go to a shop, the shopkeeper only chekcs that the money is not real or fake. He/she doesn't need to know if you are the legal bearer of that money.Similarly, If an interceptor can access JWT, he can also access the secured endpoints with that token. So transfer JWT should be done with Https and other secure protocols.
-
Second, JWT should be stored in the browser via the httponly cookie. Because JavaScript cannot access this "httponly" cookie in the browser. But JavaScript can access other cookies and local storage items.
-
Third, The csrf-token must be used to avoid CSRF (Cross-site Request Forgery) and XSS (Cross-site scripting) attacks. There is lot to discuss in this topic.But it should be in another blog.
-
Then?? No, there are no final points. You must have to be careful with the above.
However, to ensure the security of the token-based authentication system, there are many things to keep in mind. Checking the iss (issuer), using appropriate encryption algorithm, proper selection of token lifetime based on the use case, using Private-Public key pair, avoiding jwt for the session, using refresh token properly, etc should be also in your consideration.
Alternatives of JWT
JWT has most of the modern security features in it. Like, you can use public-private key pair, use secure encryption algorithm, and even you can sign the JWT. But nothing comes by default. You have to manually pass the parameters on it while generating a token. And misuse of the JWT produces security vulnerabilities. Some people even hate JWT for this reason. That’s why they go for other alternatives of JWT. Some of them are Fernet, Branca, PASETO etc.
But before choosing an alternative you have to judge them by a few standards and solve the trade-off among them. Such as whether they support public-private key encryption, are they recognized by standard authorities? Do they support symmetric encryption algorithms? Do they check standard claims such as issuer, audience, expiry time, etc? Do they use a cipher suite? No one beats JWT. But individually they offer some special features. Like, Fernet provides a default encryption feature but does not provide public-key encryption. Branca uses the latest and modern crypto algorithm. PASETO has the potential to compete with JWT but it is not standardized that much. Best option is to study your use cases well and then choose the appropriate one that meets your requirements.
With this article at OpenGenus, you must have the complete idea of JWT and It's Best Practices.