Building stateless web application with JWT

10
Clap

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

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

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 were 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 are not accessible in javascript. As the cookies are set as “httpOnly”, these cookies cannot be read from javascript but the 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 the server uses this to verify whether the request is authentic. Once JWT verification is successful, the server grants 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 a stateless session with JWT?

In a typical JEE application, we store information in session using session.setAttribute. This information is retrieved further in subsequent calls using session.getAttribute method. In general, sessions are stored in memory. If there are multiple application servers which is load-balanced then it requires us to configure as sticky session in the load balancer. In a sticky session once a session is established, all requests 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 requests.

Sharing session via distributed cache:

It is certainly possible to use a distributed cache for storing sessions. 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 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 a 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 “.”. The first part is the “header”, the second part is the body and the third part is the signature. JWT tokens are signed by a “secret” key known only to the application server. If all the application servers 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 servers 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 web service API.  Thereby eliminating the need for having different authentication mechanisms for both UI and APIs.

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” (maybe the gateway can insert it before the application server gets the request).

CSRFToken

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 servers 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.


Also published on Medium.