Building stateless web application with JWT

Storing JWT in cookies with secure and httpOnly flag is considered a better approach than storing in localStorage or in javascript local variable because of XSS attack. If you like to know more about why it is better to have JWT in cookies please read my blog post

Why should we use JWT, can we not use the same session id (JSESSIONID in java world)? It is certainly a choice based on the trade off but JWT has some benefits which was really helpful in applications that I have worked with. As the JWT is in cookies with secure and httpOnly flag, it may raise a question on how should one access user information in JWT in client especially while the JWT cookies is not accessible in javascript. As the cookies is set as “httpOnly”, these cookies cannot be read from javascript but browser will submit it with any request made to the server automatically. JWT cookies cannot be read in the javascript but user details are still needed in the javascript for displaying it in the UI or to get the user privileges to decide what features and functionality to be allowed.

I see there are two way to get user information if you are using JWT,

Option 1) JWT is issued in cookies typically in response to an authentication request made by the user by submitting valid credentials. One way to access client details is to use the body of the response to send the user information (what is present in jwt) to the client. This way although javascript cannot access JWT in cookies, it can parse the response body to get the user details.

Option 2) Once authenticated, JWT is used as an authentication token and server uses this to verify whether the request is authentic. Once JWT verification is successful, the server grant access to the web service. Hence it is possible to provide a web service to fetch user details from the server after authentication using the JWT itself. But option 2 will need an additional round-trip to the server to fetch user details.

Achieving stateless session with JWT?

In a typical JEE applications, we store information in session using session.setAttribute. This information is retrieved further in subsequent calls using session.getAttribute method. In general session are stored in memory. If there are multiple application server which are load balanced then it requires us to configure as sticky session in load balancer. In a sticky session once a session is established, all request from the same client/user will have to be sent to the same application server. If the server holding the session goes down then the user will lose the session and may have to login again to access the application.

If the application also provides service API (like REST microservice) which are typically stateless, then it is required to identify another way to authenticate & authorize these service request.

Sharing session via distributed cache:

It is certainly possible to use distributed cache for storing session. Hence whenever a server creates a session it has to be distributed to other application servers in the cluster. This becomes a challenge especially if it requires to support auto scaling.

[Auto Scaling: Auto Scaling is a way to add or remove additional servers dynamically based on factors like request, resource usage or other predictions]

Tomcat (the server I use for my applications) server has simpleTcpCluster which allows for session replication in a clustered environment. This requires multicast address and a port to be opened in all tomcat servers.

How JWT solves this?

JWT token contains 3 parts each separated by dot “.”. First part is “header”, second part is the body and third part is the signature. JWT tokens are signed by a “secret” key known only to the application server. If all the application server in a cluster have the same “secret” that is used to sign the message then it also means they can compute & verify the incoming JWT signature. This way all application server can generate and verify JWT token signature (validity & authenticity) irrespective of which application server issued a JWT token. Hence the load balancer can proxy the request to any application server to handle it.

This way the application server can be completely stateless. Also a JWT can be used both by the UI as well as for webservice API’s. There by eliminating the need for having different authentication mechanism for both UI and API’s.

SPECIAL NOTE: IT IS TO BE NOTED JWT CAN BE USED “BY VALUE” AND “BY REFERENCE”. The above use case assumes that JWT is used “By Value” or the application server gets the request with JWT “By Value” (may be gateway can insert it before application server gets the request).

CSRFToken

In order to avoid cross site request forgery especially in the browser UI it is better to have CRSFToken. More details about it in the below post,

(http://www.webagam.com/2018/10/24/how-to-use-jwt-tokens-for-secure-access/.

Since an additional CSRFToken is used, it also means all server should be able to understand CSRFToken to validate that CSRFToken is indeed a valid one. I can think of 2 possibilities,

Option 1) CSRFToken can be a unique id generated by a shared secret similar to JWT. This way each application server can validate it individually.

Option 2) CSRFToken alone can be stored in a central database and hence application server can make a single call to the DB to validate.

Hope this post was useful.


Originally published at Web Agam — Inside Tech.