Modern web applications require individuals to verify their identity. The process of verifying the identity of an individual is called Authentication. As HTTP is a stateless protocol, every call to the server is a fresh call with no trace or state of previous calls. So the only way to remember the states of the application is either by using sessions or tokens of the user so that there is no need for that user needs to log in again and again to access the application.
So in this blog we will contrast and compare mainly 2 approaches for session management:
1. Cookie or Session based approach
2. JSON Web Token (JWT) based approach
Cookie or Session based approach
This approach is the traditional approach to authenticate user which is stateful where we use session to keep track of the authenticated user. Here is the flow of the user journey in this approach:
- Authentication request is sent from the user (username and password)
- The request reached server
1). The server authenticate the user
2). The server then creates a session token, stores that token along with user's info in some database (the session ID should be opaque string).
- Server then sends the cookie with the sessionID to the browser.
- Browser then incudes the cookie within every subsequent request to the server so that it can identify the user.
- When server receives the cookie with session token it won’t know who the user is
1). So it sends it to the database to retrieve the user (5.1) from the token
2). If the user exists in the database the database will return the user info (5.2)
3). Then the server will the process the request(5.3)
4). Stores the processed request to database.
- Then server will send sucess message to the client.
This approach affects overall response time because the call to DB is slower and should be repeated for every request sent by the client.
Idle Session management
Idle session management refers to the practice of handling and controlling user sessions that have become inactive or idle for a certain period of time. Proper management of idle sessions is crucial for security, resource utilization, and user experience. It involves implementing policies and mechanisms to address scenarios where users have logged into a system but are no longer actively using it.
In traditional approach following parameters can be taken into consideration for idle session management:
- Session Timeout: Define a session timeout period after which an idle session will expire. If the user does not interact with the application within this timeframe, their session will be terminated, requiring them to log in again.
- Session Renewal: Allow users to renew their session by performing an action (e.g., clicking a button) before it expires. This prevents sudden session terminations while maintaining security.
- Inactivity Detection: Implement mechanisms to detect user activity or interaction. If the application detects inactivity beyond a certain threshold, it can initiate the countdown to session expiration.
- User Notifications: Notify users when their session is about to expire, giving them a chance to extend their session if needed.
Auto Expiry Handling
Auto expiry handling in session-based authentication involves automatically managing the expiration of user sessions to enhance security and user experience. Here's a general approach to implementing auto expiry handling in session-based authentication:
Session Timeout Configuration:
- Define a session timeout value based on your application's security and user requirements. Common values range from a few minutes to several hours.
- Allow administrators to configure different session timeout values for different user roles or application sections.
Last Activity Tracking:
- Record the timestamp of the user's last activity within their session. Activities could include page visits, interactions, or requests to the server.
Automatic Logout Mechanism:
- Implement a background process that periodically checks the duration of inactivity for each session.
- If the duration of inactivity exceeds the configured session timeout, automatically log the user out by invalidating their session.
Explicit logout is important for security and user privacy. It will give user sense that they have control over their active sessions and helps prevent unauthorized access to user accounts.
In traditional approach this is done by the following steps :
- Creating the endpoint at server side for logout that will handle session termination logic.
- From user side we can have the button that will call this endpoint whenever user clicks on this button.
- Server side logic:In the server, when a request is made to the logout endpoint, perform the following steps:
- Invalidate Session: Delete the session associated with the user. This could involve removing session data.
- Clear Cookie: Clear any session-related cookies from the user's browser. For example, if we are using an HTTP-only cookie to store the session token, setting up max-age to 0 will delete the cookie.
4. On successful logout we can redirect the user to the login page
- Precision logout i.e. as soon as sessionId is removed from the DB logout occurs.
- Battle-tested 20+ years in many languages and frameworks.
1. This approach affects overall response time because the call to DB is slower and should be repeated for every request sent by the client.
The above-mentioned problem can be solved using 2 ways
- Making DB calls much faster that it won't matter. This can be done by replacing the normal DB with the Redis .
2. We can eliminate DB lookup by following the methods
- We can store the state of the user by the server in memory storage.But this has one downside while scaling the state of the user is only available on a specific server.
- We can use the JWT approach which we are seeing in the next section
3. Cross-site scripting (XSS) attacks:
Session-based authentication is vulnerable to XSS attacks, in which a malicious script is injected into a web page and executed by the victim’s browser, allowing an attacker to steal the user’s session ID or other sensitive information.
We can mitigate the risk associated with XSS by proper cookie attribute configuration
- Same-Site: The "Same-Site" attribute determines whether cookies should be sent along with cross-site requests. By setting this attribute to "Strict" or "Lax," you can control when cookies are transmitted. This helps prevent CSRF attacks and reduces the risk of session exposure.
- Lax: Cookies with the "Lax" attribute are sent with top-level navigations (for example clicking on links) and are restricted for use with potentially unsafe cross-site requests. This mitigates the risk of certain CSRF attacks by not sending cookies with requests initiated by third-party sites.
- Strict: Cookies with the "Strict" attribute are only sent in secure contexts (i.e., over HTTPS). This helps prevent the transmission of cookies over insecure connections, reducing the risk of interception through attacks like Man-in-the-Middle
4. Server-side vulnerabilities: Session-based authentication does not protect against server-side vulnerabilities, such as SQL injection or file inclusion attacks. It is important to implement other security measures, such as input validation and output encoding, to prevent these types of attacks.
JSON Web Token (JWT) based approach
JWT eliminates the problem of DB lookup when used as a session
In this approach, the user info is stored in the session token itself. To secure the user's info part of the token is signed using a secret which is only known to the server.
JSON Web Token structure
In its compact form, JSON Web Tokens consist of three parts separated by dots (.), which are:
The header typically consists of two parts: the type of the token, which is JWT, and the signing algorithm being used, such as HMAC SHA256 or RSA.
Contains the claims that provide information about a user who has been authenticated along with other information such as token expiration time
This part is dependent on the encoded header, encoded payload, a secret, and the algorithm specified in the header and sign.
Here is the flow of the user journey in this approach:
- The authentication request is sent from the user (username and password)
- The request reached server
1. The server authenticates the user
2. The server creates JWT session token using the user's info without making DB call
- This JWT token is sent to the user for future use (may be in the form of a cookie or form of response).
- The browser then incudes the cookie (JWT Token) within every subsequent request to the server so that browser can identify the user.So when the browser receives the JWT token it uses the secret to validate the signed part and gets the user info. Even this doesn't include DB.
Idle Session management
In token-based authentication mechanism where a digitally signed token is used to verify a user's identity. Unlike session-based authentication, JWTs are self-contained and do not require server-side storage of session data.
Idle session management in JWT-based authentication can be approached in the following ways:
- Shorter Token Expiry: Issue JWTs with shorter expiration times. This limits the window of opportunity for an attacker to use a stolen JWT.
- Token Revocation: Provide a mechanism for users to revoke their tokens, especially if they suspect unauthorized access or have lost their device.
- Refresh Tokens: Alongside short-lived access tokens, use longer-lived refresh tokens. When the access token expires due to inactivity, users can exchange a refresh token for a new access token without needing to re-enter their credentials.
- User Notifications: Similar to session-based authentication, notify users about expiring tokens or provide an option to renew the token.
- Regular Token Renewal: Implement a mechanism where users are prompted to re-authenticate (e.g., enter their password) after a certain period of inactivity to obtain a new access token.
Auto Expiry Handling
Auto expiry handling in JSON Web Token (JWT) based authentication involves managing the automatic expiration of JWTs to ensure security and control access to resources. Here's how you can implement auto expiry handling in JWT-based authentication:
Token Expiry Claim :
- Include an expiration time claim in the JWT payload. This claim specifies the timestamp when the token should expire. The value of the this claim should be a Unix timestamp in seconds.
- When generating a JWT for a user during authentication, set the expiry time claim to the desired expiration time. Typically, tokens are issued with short expiration periods (e.g., minutes to hours) for security.
- When a token is received from a client, ensure that it hasn't expired by checking the "exp" claim against the current timestamp.
- Without sessionStore the same token is used to authenticate on different server as well, as long as the server have the SECRET key.
- As it doesn't involve DB call to get the session info its much faster than the traditional approach.
- Since JWT is self-contained and will continue to work until it expires. So even if logout happens if someone gets the token they can still able to log in with that and get the user info. To avoid this server need to maintain a blacklist of revoked tokens which defeats the purpose of stateless tokens.
- Anyone able to perform a man-in-middle attack and sniff the JWT and authenticate the individual credentials because JWT is rarely encrypted.
- In many real world applications, we may need to store a ton of different information. And storing it in the JWT tokens could exceed the allowed URL length or cookie lengths causing problems. And also we are now sending large volume of data on every request which will cause the network overhead and server may take slightly more time to decode and verify.
Ultimately, the choice depends on factors such as security requirements, scalability needs, and the nature of your application. JWTs are ideal for stateless, distributed systems with a focus on scalability and single sign-on, while session-based approaches are more appropriate for applications that prioritise server-side control, robust session management, and sensitive data protection.
It's worth noting that both approaches have their own security considerations, and proper implementation and adherence to best practices are crucial regardless of the chosen method. As technology evolves, staying updated on the latest security guidelines and industry trends is essential for maintaining a secure and reliable authentication system.
Scalability, reliability and maintainability are the three pillars that govern what we build at Halodoc Tech. We are actively looking for engineers at all levels and if solving hard problems with challenging requirements is your forte, please reach out to us with your resumé at email@example.com.
Halodoc is the number 1 all around Healthcare application in Indonesia. Our mission is to simplify and bring quality healthcare across Indonesia, from Sabang to Merauke. We connect 20,000+ doctors with patients in need through our Tele-consultation service. We partner with 3500+ pharmacies in 100+ cities to bring medicine to your doorstep. We've also partnered with Indonesia's largest lab provider to provide lab home services, and to top it off we have recently launched a premium appointment service that partners with 500+ hospitals that allow patients to book a doctor appointment inside our application. We are extremely fortunate to be trusted by our investors, such as the Bill & Melinda Gates Foundation, Singtel, UOB Ventures, Allianz, GoJek, Astra, Temasek, and many more. We recently closed our Series D round and in total have raised around USD$100+ million for our mission. Our team works tirelessly to make sure that we create the best healthcare solution personalised for all of our patient's needs, and are continuously on a path to simplify healthcare for Indonesia.