Securing JavaScript Applications with JSON Web Tokens (JWT)

What is JWT security? JWT security involves validating signatures, using strong algorithms, limiting token lifetime, and storing tokens safely so attackers cannot forge or replay authentication tokens.

IoT Device Testing

The following article is a discussion that explores JavaScript Web Tokens, and how developers generate JWT signing keys and how they create, verify, and terminate sessions.

Table of Contents

Background

JavaScript web tokens are well documented and are used for authentication. JWT’s consist of three parts; the header, payload and signature. The header is used to describe the JWT, specifically, it will indicate how the signature is calculated. The payload of the JWT will contain claims about the user presenting the JWT, claims are just another word for attributes. There are a few predesignated claims there should be included in your JWT, other claims can be free form, that means the payload can contain any data that the developer wants it to contain. The signature is used to prevent tampering of the JWT.  The most common signing algorithms are HS256, RS256, and ES256, however, there are other algorithms.  One of the most important claims that should always exist in the payload is the “exp” claim. The “exp” claim represents the epoch time that the JWT will expire, without this claim the JWT is valid forever.

The expiration claim on the JWT introduces an interesting issue with session management, when a user intentionally terminates a session, how do you invalidate the JWT?  A common design pattern that I see on application tests is for the client-side application to receive a JWT from the server and then store it in the browser’s session storage. Subsequent Ajax requests will include the JWT as a bearer token in the authorization header.  When a user intentionally terminates a session, otherwise known as logging out, the application will simply delete the JWT from the browser’s session storage. This has the effect of causing the browser to believe the session was terminated because the application can no longer authenticate to the server since the application can no longer find the JWT in the session store.  However, this is an illusion, deleting the JWT from the session store does nothing to invalidate the session, the deleted JWT will remain valid until the expiration date has been reached. If an attacker had captured the JWT, they would be able to use it until the exp claim lapses.  This type of session handling runs afoul of the OWASP best practices, OWASP states that a secure session termination requires at least the following components.

  • Availability of user interface controls that allow the user to manually log out.
  • Session termination after a given amount of time without activity (session timeout).
  • Proper invalidation of server-side session state.

This leaves the developer with the before mentioned question, how can a JWT be invalidated when the user logs out?  One solution that I have heard is to have short lived expirations and to use a refresh token to re-issue the JWT upon expiration.  While this solution limits the window in which an abandoned session could be used, it doesn’t actually solve the problem.  I have seen a few other recommendations that should work in theory, but they are not always practical or easy to implement. Below I describe the easiest method that I have found.  It makes changes to how developers generate JWT signing keys and how they create, verify, and terminate sessions.

Session Creation

When the session is created, the session key should be generated and stored in the datastore.  For the purposes of this writing, it will be assumed the datastore is a database table with the following fields.

  • SessionID GUID
  • SessionKey TEXT
  • ExpirationDate Timestamp

Once the JWT is populated and ready to be signed, the KID claim should be populated with the SessionID GUID and the JWT should be signed with the SessionKey value as demonstrated with the below pseudo code.

				
					$key = SecureRandom.Generate(32); // 32 random bytes

$id = GUID.New(); // get new 32-bit GUID

$expires = date_add($now, “1h”); // expire in 1 hour

$db.execute(“insert into SessionKeys(SessionID, SessionKey, ExpirationDate) values(?, ?, ?)”, $id, $key,$expires);

$header = {“alg”:”HS256”, “kid”:”$id”}

$payload = {“exp”:”$expires”}; // insert claims here

$jwt = JWT.sign($header, $payload, $key)
				
			

Session Verification

When it is time to verify the JWT, the application should read the KID claim and lookup that value in the database using the below pseudo code.

				
					$qSession = $db.Query(“select * from SessionKeys where SessionID = ?”, $jwt[“kid”]);
				
			

It goes without saying that parameterized statements should always be used when querying a database.

				
					$isvalid = JWT.verify($jwt, $qSession[“SessionKey”]);
				
			

When the user initiates a logout, the JWT verified using the process outlined above and then the session key should be deleted from the database as shown in the below pseudo code.

				
					$qSession = $db.Query(“select * from SessionKeys where SessionID = ?”, $jwt[“kid”]);

$isValid = JWT.verify(jwt, qSession[“SessionKey”]);

If($isValid)

{

               $db.execute(“delete from SessionKeys where SessionKey = ? or ExpirationDate <= ?”, $qSession[“SessionID”], $now);

}
				
			

Session Termination

By deleting the session key, the JWT is no longer able to be validated and is now in a de facto state of being expired.  The “or ExpirationDate <= $now” portion of the above pseudo code does some automated garbage collection by deleting the current session and any sessions that have already expired.  At this point, it is safe for the client-side application to delete the JWT from session storage.

Conclusion

JWTs are a convenient way to implement authentication, however they are not without their complexities, managing JWTs can be likened to managing PKI.  With PKI, it can be difficult to invalidate certificates once they are issued, revocations require a whole other process (CRLs) to maintain a healthy PKI.  The same can be said for managing JWT’s, however, the revocation process can be simplified using the process outlined in this writing.

Anthony Cole

Anthony Cole is a Sr. Security Consultant with over 22 years of experience in information technology, IT security and software development. Anthony is fully GIAC certified in all facets of information security, enabling him to facilitate successful outcomes for customers. Anthony’s vast knowledge of both offensive and defensive security ensures that Redbot Security’s customers will receive the best service in the industry.

Anthony is Redbot Security’s AppSec SME and formerly a Sr. Level Application Penetration Testing Engineer for NetSpi and Presidio as well as Blutique LLC’s Chief Technical Officer and Sr. Application Developer.

Book a discovery call or request a rapid quote for services, tailored to your priorities and budget

From manual testing of IT Networks and Web / Mobile Applications to advanced Red Team operations, Cloud Security, and OT-network assessments, Redbot Security delivers laser-focused, senior-level expertise,  without breaking the bank.

Related Articles

Moody cyberpunk doctor’s office with red and electric blue tech mesh lighting across walls and floor, representing healthcare cybersecurity and HIPAA physical security risks

Physical Security & HIPAA: 2025 Healthcare Breach Review

Physical security failures were a major factor in 2025 healthcare breaches. With HIPAA’s proposed 2026 updates making physical safeguards mandatory, organizations must strengthen facility controls, workstation protections, and device security. Redbot Security’s physical penetration testing helps identify real-world risks and prepare for upcoming regulatory requirements.

Dark cyberpunk image representing modern web application exploitation, API abuse, business logic attacks, and 2026 real-world cyber threats.

Beyond OWASP Top 10: The Real-World Web App Exploits Attackers Are Using in 2026

The OWASP Top 10 is no longer enough to defend modern applications. In 2026, attackers are exploiting API logic flaws, cloud misconfigurations, serverless components, and real-world multi-step attack chains that scanners can’t identify. This article breaks down the real threats facing web apps today—and why manual testing is essential.

Dark industrial control room with faint electric-blue grid lines and red cyberpunk accents, representing OT network testing across ICS and SCADA environments.

OT Network Testing: Purdue, NIST & Redbot’s Critical Infrastructure Approach

America’s critical infrastructure faces rising cyber threats while legacy OT systems and shrinking federal support leave operators exposed. This article explores how Redbot Security uses Purdue and NIST methodologies to deliver safe, manual, and holistic OT network testing that protects ICS environments from real-world disruption.

© Copyright 2016-2025 Redbot Security