In view with our honourable Prime Minister’s vision of a ‘New India by 2022‘, the Indian Government identified 117 aspirational districts across 28 states for rapid transformation and inclusive growth.
These districts, which lag on several key indicators and specific developmental parameters, were selected on the basis of composite index across five sectors:Health and Nutrition, Education, Agriculture and Water resources, Financial Inclusion, and Skill development.
To link the ‘Supportive Supervision‘ mechanism and improve program performance, we developed a supportive supervision software for aspirational districts named ADARSSH.
The application was expected to have a design that was less expensive and can run and easily scaled up to handle huge workloads.
On further research, our team found out one of the key areas where we could cut cost – session management of users using JSON Web Token (JWT). I am going to explain why our team decided to go with JWT followed with the working details of JWT tokens.
HTTP, being a stateless protocol, does not take any responsibility of session management of users in an application. Therefore, to identify users between consecutive HTTP requests, session management was introduced and it became the responsibility of the application to handle it. Based on the way an application handles a session, the application was categorized as:
Stateful sessions are stored in RAM of the server where the application is running. This makes the application unreliable as users’ sessions are destroyed with server restarts, which gives users a bad experience as they are logged out since their session has got lost.One way to solve this problem was to add multiple server instances and synchronize session to these instances of server when session is created or updated. That give us reliability i.e. even if session is lost in one of the instances it can be found in another instance.
Stateless sessions are more reliable that can withstand the loss of losing sessions on server restarts because the session data is stored in a persistent storage rather than volatile storage like RAM. This gives users of our application a seamless experience i.e. their session is not logged out even if the application server restarts. Generally, in case of stateless session the session is persisted or stored in the database.
So, with stateless sessions comes the cost of storage and blocking I/O. The session must be retrieved, persisted, or both on every access to session at application layer.
JWT brings a new dimension to stateless applications – instead of storing sessions on server side, we can store them on client side. JWT eliminates the need for storage in stateless application, which reduces costs, prevents loss of sessions on server restarts, as well as the need to store and retrieve sessions from persistent storage.
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between client and server as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA. We are going to focus on public/ private key pair using RSA.
The above workflow can be best described as follows:
- The application send credentials to the authorization server to get a JWT Token
- After, authentication, the authorization server returns a JWT token as access token
- The application calls the Resource Server by passing the JWT token in Authorization request header. The Resource Server validates the JWT then makes a test of Authorization, and allows access to API after which the client receives the response.
One of the benefits of asymmetric public/private key encryption is that the public key can be shared to public, whereas the private key can be kept private i.e. if we have a distributed system, we can arm a server with private key that will be responsible for generating tokens. We can call this server as Authorization server. While other downstream services (Resource Server) can have public key with them so that, they can validate the received token from HTTP requests from client (Browser / Mobile).
The asymmetric cryptography enables us to use two workflows:
Message encryption: Data encrypted using public key can only be decrypted by private key. This enables us information exchange between client and server securely.
Public key encrypts => private key decrypts
Message Signing: A server sends message to clients and the clients to verify the message, originated from server. The server signs the message with private key and the client can verify the message with public key.
Private key signing => public key verify signature
Let us have a look at a JWT token. The token consists of a Header, Payload and Signature. A sample token is attached below.
A JWT signed with a private key can be verified with the corresponding public key.
The JWT is base64 encoded as seen in left side of picture. The content has two dots(.) that separates different parts of token. The decoded token can be seen on right side of picture. The token has following things:
- The header contains information related to type of algorithm used to generate the token.
- The payload can contain session related information like username to identify the user between multiple subsequent HTTP requests.
- The signature contains the output generated by signing the (header + payload) with private key.
Let us discuss how tokens is generated at Authorization Server equipped with private key and how Resource Servers validate the token using public key.
The Authorization server receives request for authentication, the server authenticates the user and generates a JWT token by:
Let us say if we are using RS256 which is a combination of RSA + SHA256, the header and payload is hashed with hashing algorithm SHA256. Then the generated hash called digest, is encrypted with the private key.
The header and payload is attached with the signature generated to have the final token.
Header + Payload => Hashed With SHA256 (Digest) => Encrypt with RSA = Signature.
The signature is last part of JWT token attached after two dots in the token.
The resource server armed with public key receives the token. The resource server extracts first two parts of token i.e. header and payload hashes with the hashing algorithm i.e. SHA256 to get the digest from (header + payload).
Header + Payload => Hashed With SHA256 = Digest.
Then the resource server extracts the signature from the original token i.e. third part of token. It decrypts the signature using public key to get the digest. Then it compares both the hashes i.e. digests to validate the token.
Signature => Decrypted With Public Key = Digest
Note: during decryption of signature, only the signature encrypted with right private key can be decrypted with the public key.
By this way the signature is used to ensure integrity of the token by recalculating the signature-using header and payload and matching with signature. This way, if any tampering of header and payload has happened would be detected.
Thank you for spending time in reading this blog and we would like to invite you to join us in this exciting journey.