{
    "componentChunkName": "component---src-pages-blog-markdown-remark-fields-slug-js",
    "path": "/blog/revoking-access-with-a-jwt-blacklist",
    "result": {"data":{"markdownRemark":{"html":"<h2 id=\"table-of-contents\" style=\"position:relative;\"><a href=\"#table-of-contents\" aria-label=\"table of contents permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Table of Contents</h2>\n<ol>\n<li><a href=\"#why-revoking-jwt-tokens-can-be-challenging\">Introduction</a></li>\n<li><a href=\"#a-word-or-two-about-json-web-tokens-jwts\">A Word or Two About JSON Web Tokens (JWTs)</a></li>\n<li><a href=\"#7-ways-to-revoke-jwt-tokens\">7 Ways to Revoke JWT Tokens</a></li>\n<li><a href=\"#how-to-make-access-token-management-easier\">How to Make Access Token Management Easier</a></li>\n<li><a href=\"#risks-of-improper-access-token-management\">Risks of Improper Access Token Management</a></li>\n<li><a href=\"#conclusion\">Conclusion</a></li>\n</ol>\n<h2 id=\"why-revoking-jwt-tokens-can-be-challenging\" style=\"position:relative;\"><a href=\"#why-revoking-jwt-tokens-can-be-challenging\" aria-label=\"why revoking jwt tokens can be challenging permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why Revoking JWT Tokens Can Be Challenging</h2>\n<p>JSON Web Tokens (JWT) are a fundamental part of modern web authentication and authorization systems, particularly in applications where secure and efficient user authentication is critical. Due to their stateless nature, JWTs are widely adopted, but managing and revoking these tokens presents unique challenges that developers must carefully address to maintain the security and integrity of their systems.</p>\n<p>This article delves into seven effective strategies for revoking JWT tokens, ensuring secure access management while navigating the complexities associated with JWTs.</p>\n<h3 id=\"a-word-or-two-about-json-web-tokens-jwts\" style=\"position:relative;\"><a href=\"#a-word-or-two-about-json-web-tokens-jwts\" aria-label=\"a word or two about json web tokens jwts permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>A Word or Two About JSON Web Tokens (JWTs)</h3>\n<p>JWT tokens, or JSON Web Tokens, are self-contained tokens used in authentication systems to securely transmit information between parties. These tokens include a payload that carries claims, such as the user’s ID, roles, or other relevant details about the user’s data, and are signed using a secret key.</p>\n<p>The signed JWT is then sent to the client and used in subsequent requests, typically passed in the Authorization header. This stateless nature makes JWTs a popular choice for authentication in distributed systems, as it removes the need for maintaining a server-side session state.</p>\n<p>However, the statelessness of JWTs also poses significant challenges when it comes to revocation. Unlike traditional session-based authentication, where sessions can be invalidated by removing them from the server, JWTs remain valid until their expiration (<code class=\"language-text\">exp</code>) time, which is embedded within the token’s payload.</p>\n<p>This expiry time ensures that the token is valid only for a specified period, but it can be problematic when a user’s account is compromised. Since the token cannot be easily invalidated across all endpoints without a centralized mechanism, any delay in detecting and revoking the token can result in unauthorized access to the user’s data.</p>\n<p>Additionally, in distributed systems where multiple services or microservices rely on the same JWT access token, revocation becomes even more complex. Each service must recognize and enforce the revocation, which can be challenging without a shared state or revocation strategy. This complexity is further compounded when integrating with identity providers that issue JWTs as part of OAuth 2.0 or OpenID Connect protocols. It is recommended to refer to platform-specific documentation (docs) or GitHub repositories to implement best practices for revoking JWTs in such relatively complex environments.</p>\n<h2 id=\"7-ways-to-revoke-jwt-tokens\" style=\"position:relative;\"><a href=\"#7-ways-to-revoke-jwt-tokens\" aria-label=\"7 ways to revoke jwt tokens permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>7 Ways to Revoke JWT Tokens</h2>\n<p>Effectively revoking JWT tokens requires implementing strategies that accommodate their stateless design while ensuring security. Here are seven methods to revoke JWT tokens, each with its pros and cons.</p>\n<h3 id=\"token-blacklisting\" style=\"position:relative;\"><a href=\"#token-blacklisting\" aria-label=\"token blacklisting permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Token Blacklisting</h3>\n<p><strong>How It Works:</strong></p>\n<p>Token blacklisting is a widely used method to revoke JWT tokens. This approach involves maintaining a server-side blacklist containing identifiers, such as the <code class=\"language-text\">jti</code> claim or a user ID, of tokens that should be considered invalid.</p>\n<p>When a token is presented at an API endpoint, the server checks the blacklist to determine whether the token has been revoked. This list can be stored in a database or in an in-memory store like Redis, which allows for quick lookups.</p>\n<p><strong>Pros:</strong></p>\n<ul>\n<li><strong>Granular Control:</strong> Token blacklisting provides the ability to revoke specific tokens without affecting others, offering fine-grained control over user sessions.</li>\n<li><strong>Compatibility:</strong> This method can be integrated with various backend systems and identity providers, making it a versatile solution for developers who follow guidelines and examples from GitHub or similar platforms.</li>\n</ul>\n<p><strong>Cons:</strong></p>\n<ul>\n<li><strong>Scalability Issues:</strong> As the number of blacklisted tokens increases, the performance of blacklist lookups may degrade, especially if stored in a database.</li>\n<li><strong>Stateful Requirement:</strong> Blacklisting necessitates maintaining a server-side state, which conflicts with the stateless nature of JSON Web Tokens.</li>\n</ul>\n<p><strong>Example in Node.js:</strong></p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"61774448850358630000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`const redis = require('redis');\nconst client = redis.createClient();\n\nfunction blacklistToken(jti) {\n  client.set(jti, 'revoked', 'EX', 3600); // Expiry set for 1 hour\n}\n\nfunction isTokenRevoked(jti, callback) {\n  client.get(jti, (err, reply) => {\n    callback(reply === 'revoked');\n  });\n}\n\n// Middleware to check token blacklist\nfunction checkBlacklist(req, res, next) {\n  const token = req.headers['authorization'];\n  const secret = process.env.JWT_SECRET;\n  const decoded = jwt.verify(token, secret);\n\n  isTokenRevoked(decoded.jti, (isRevoked) => {\n    if (isRevoked) {\n      return res.status(401).send('Token has been revoked');\n    }\n    next();\n  });\n}`, `61774448850358630000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> redis <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'redis'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> client <span class=\"token operator\">=</span> redis<span class=\"token punctuation\">.</span><span class=\"token function\">createClient</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">blacklistToken</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">jti</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  client<span class=\"token punctuation\">.</span><span class=\"token function\">set</span><span class=\"token punctuation\">(</span>jti<span class=\"token punctuation\">,</span> <span class=\"token string\">'revoked'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'EX'</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3600</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Expiry set for 1 hour</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">isTokenRevoked</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">jti<span class=\"token punctuation\">,</span> callback</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  client<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span>jti<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">err<span class=\"token punctuation\">,</span> reply</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">callback</span><span class=\"token punctuation\">(</span>reply <span class=\"token operator\">===</span> <span class=\"token string\">'revoked'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token comment\">// Middleware to check token blacklist</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">checkBlacklist</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">req<span class=\"token punctuation\">,</span> res<span class=\"token punctuation\">,</span> next</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> token <span class=\"token operator\">=</span> req<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">[</span><span class=\"token string\">'authorization'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> secret <span class=\"token operator\">=</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">JWT_SECRET</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> decoded <span class=\"token operator\">=</span> jwt<span class=\"token punctuation\">.</span><span class=\"token function\">verify</span><span class=\"token punctuation\">(</span>token<span class=\"token punctuation\">,</span> secret<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token function\">isTokenRevoked</span><span class=\"token punctuation\">(</span>decoded<span class=\"token punctuation\">.</span>jti<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">isRevoked</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>isRevoked<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">return</span> res<span class=\"token punctuation\">.</span><span class=\"token function\">status</span><span class=\"token punctuation\">(</span><span class=\"token number\">401</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">send</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Token has been revoked'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token function\">next</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>In this example, a JWT token’s <code class=\"language-text\">jti</code> (JWT ID) is stored in Redis when the token is revoked. The middleware checks if the token’s <code class=\"language-text\">jti</code> exists in Redis before processing the request.</p>\n<h3 id=\"token-expiration-and-short-lifespan\" style=\"position:relative;\"><a href=\"#token-expiration-and-short-lifespan\" aria-label=\"token expiration and short lifespan permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Token Expiration and Short Lifespan</h3>\n<p><strong>How It Works:</strong></p>\n<p>Setting a short lifespan (the <code class=\"language-text\">exp</code> parameter) for JWT tokens can mitigate the risks associated with needing to revoke them. By configuring JWTs with a short expiration time, you reduce the window of opportunity for an attacker to use a compromised token.</p>\n<p>Once the token reaches its expiry, it becomes invalid, and the user must obtain a new JWT access token, typically through re-authentication or using a refresh token.</p>\n<p><strong>Pros:</strong></p>\n<ul>\n<li><strong>Reduced Exposure:</strong> Short-lived tokens minimize the risk associated with compromised tokens by ensuring they are only valid for a limited time.</li>\n<li><strong>Maintains Statelessness:</strong> This approach retains the stateless nature of JWTs as no server-side storage is required for token management.</li>\n</ul>\n<p><strong>Cons:</strong></p>\n<ul>\n<li><strong>User Experience Impact:</strong> Users may need to authenticate more frequently, potentially leading to a frustrating user experience.</li>\n<li><strong>No Immediate Revocation:</strong> This method does not provide a way to immediately revoke tokens, which can be a drawback if a user’s account is compromised.</li>\n</ul>\n<p><strong>Example in Node.js:</strong></p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"24619891939077430000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`const jwt = require('jsonwebtoken');\n\nfunction generateToken(user) {\n  const payload = { userId: user.id, roles: user.roles };\n  return jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '15m' });\n}`, `24619891939077430000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"ts\"><pre class=\"language-ts\"><code class=\"language-ts\"><span class=\"token keyword\">const</span> jwt <span class=\"token operator\">=</span> <span class=\"token keyword\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'jsonwebtoken'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">generateToken</span><span class=\"token punctuation\">(</span>user<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> payload <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> userId<span class=\"token operator\">:</span> user<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span> roles<span class=\"token operator\">:</span> user<span class=\"token punctuation\">.</span>roles <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">return</span> jwt<span class=\"token punctuation\">.</span><span class=\"token function\">sign</span><span class=\"token punctuation\">(</span>payload<span class=\"token punctuation\">,</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">JWT_SECRET</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> expiresIn<span class=\"token operator\">:</span> <span class=\"token string\">'15m'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>In this example, JWTs are generated with a 15-minute expiration time. Users must frequently refresh their tokens, reducing the risk associated with compromised tokens.</p>\n<h3 id=\"rotating-secrets\" style=\"position:relative;\"><a href=\"#rotating-secrets\" aria-label=\"rotating secrets permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Rotating Secrets</h3>\n<p><strong>How It Works:</strong></p>\n<p>JWT tokens are signed with a secret key that verifies their authenticity. By periodically rotating this secret key, you can invalidate all existing tokens signed with the old key. This method is particularly useful when you need to revoke a large number of tokens simultaneously, such as after a security incident or when changing your authentication strategy.</p>\n<p><strong>Pros:</strong></p>\n<ul>\n<li><strong>High Security:</strong> Regularly rotating secrets add an extra layer of security, making it more difficult for attackers to exploit a compromised key.</li>\n<li><strong>Wide Impact:</strong> Secret rotation invalidates all tokens at once, which is effective in scenarios where a large-scale revocation is necessary.</li>\n</ul>\n<p><strong>Cons:</strong></p>\n<ul>\n<li><strong>Complex Key Management:</strong> Rotating secrets requires careful management to avoid invalidating legitimate tokens inadvertently.</li>\n<li><strong>Token Recreation:</strong> After a key rotation, clients must obtain new JWTs signed with the updated key, which can complicate client-side and backend interactions.</li>\n</ul>\n<p><strong>Note:</strong> Doing secret management on your own is challenging and can open you to security vulnerabilities, so most auth services handle this on your behalf.</p>\n<h3 id=\"token-versioning\" style=\"position:relative;\"><a href=\"#token-versioning\" aria-label=\"token versioning permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Token Versioning</h3>\n<p><strong>How It Works:</strong></p>\n<p>Token versioning involves assigning a version number to each JWT issued, which is then stored in the database alongside the user’s account information. When a token needs to be revoked, the version number is incremented in the database, rendering all previous tokens invalid. The next time the user tries to authenticate, they must present a token with the updated version.</p>\n<p><strong>Pros:</strong></p>\n<ul>\n<li><strong>Selective Revocation:</strong> Token versioning allows for targeted revocation based on the user’s account status or other criteria.</li>\n<li><strong>Flexibility:</strong> This method can be integrated with various identity providers and authentication systems, offering a flexible solution.</li>\n</ul>\n<p><strong>Cons:</strong></p>\n<ul>\n<li><strong>Increased Complexity:</strong> Managing token versions adds complexity to the backend, requiring additional logic to validate token versions.</li>\n<li><strong>Database Dependency:</strong> This approach relies on database lookups to validate token versions, which can introduce latency, especially if not optimized for in-memory checks.</li>\n</ul>\n<p><strong>Example in Node.js (+ MongoDB):</strong></p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"87862625802440310000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`const mongoose = require('mongoose');\n\n// Define User schema with tokenVersion field\nconst UserSchema = new mongoose.Schema({\n  email: String,\n  password: String,\n  tokenVersion: { type: Number, default: 0 }\n});\n\nconst User = mongoose.model('User', UserSchema);\n\nfunction generateToken(user) {\n  const payload = { userId: user.id, tokenVersion: user.tokenVersion };\n  return jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '15m' });\n}\n\nasync function invalidateUserTokens(userId) {\n  await User.findByIdAndUpdate(userId, { \\$inc: { tokenVersion: 1 } });\n}\n\n// Middleware to check token version\nasync function checkTokenVersion(req, res, next) {\n  const token = req.headers['authorization'];\n  const decoded = jwt.verify(token, process.env.JWT_SECRET);\n\n  const user = await User.findById(decoded.userId);\n  if (user.tokenVersion !== decoded.tokenVersion) {\n    return res.status(401).send('Token version is invalid');\n  }\n  next();\n}`, `87862625802440310000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"ts\"><pre class=\"language-ts\"><code class=\"language-ts\"><span class=\"token keyword\">const</span> mongoose <span class=\"token operator\">=</span> <span class=\"token keyword\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'mongoose'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Define User schema with tokenVersion field</span>\n<span class=\"token keyword\">const</span> UserSchema <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">mongoose</span><span class=\"token punctuation\">.</span><span class=\"token function\">Schema</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  email<span class=\"token operator\">:</span> String<span class=\"token punctuation\">,</span>\n  password<span class=\"token operator\">:</span> String<span class=\"token punctuation\">,</span>\n  tokenVersion<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> type<span class=\"token operator\">:</span> Number<span class=\"token punctuation\">,</span> <span class=\"token keyword\">default</span><span class=\"token operator\">:</span> <span class=\"token number\">0</span> <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> User <span class=\"token operator\">=</span> mongoose<span class=\"token punctuation\">.</span><span class=\"token function\">model</span><span class=\"token punctuation\">(</span><span class=\"token string\">'User'</span><span class=\"token punctuation\">,</span> UserSchema<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">generateToken</span><span class=\"token punctuation\">(</span>user<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> payload <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> userId<span class=\"token operator\">:</span> user<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span> tokenVersion<span class=\"token operator\">:</span> user<span class=\"token punctuation\">.</span>tokenVersion <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">return</span> jwt<span class=\"token punctuation\">.</span><span class=\"token function\">sign</span><span class=\"token punctuation\">(</span>payload<span class=\"token punctuation\">,</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">JWT_SECRET</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> expiresIn<span class=\"token operator\">:</span> <span class=\"token string\">'15m'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">async</span> <span class=\"token keyword\">function</span> <span class=\"token function\">invalidateUserTokens</span><span class=\"token punctuation\">(</span>userId<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">await</span> User<span class=\"token punctuation\">.</span><span class=\"token function\">findByIdAndUpdate</span><span class=\"token punctuation\">(</span>userId<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> $inc<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> tokenVersion<span class=\"token operator\">:</span> <span class=\"token number\">1</span> <span class=\"token punctuation\">}</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token comment\">// Middleware to check token version</span>\n<span class=\"token keyword\">async</span> <span class=\"token keyword\">function</span> <span class=\"token function\">checkTokenVersion</span><span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">,</span> res<span class=\"token punctuation\">,</span> next<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> token <span class=\"token operator\">=</span> req<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">[</span><span class=\"token string\">'authorization'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> decoded <span class=\"token operator\">=</span> jwt<span class=\"token punctuation\">.</span><span class=\"token function\">verify</span><span class=\"token punctuation\">(</span>token<span class=\"token punctuation\">,</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">JWT_SECRET</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">const</span> user <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> User<span class=\"token punctuation\">.</span><span class=\"token function\">findById</span><span class=\"token punctuation\">(</span>decoded<span class=\"token punctuation\">.</span>userId<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>user<span class=\"token punctuation\">.</span>tokenVersion <span class=\"token operator\">!==</span> decoded<span class=\"token punctuation\">.</span>tokenVersion<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> res<span class=\"token punctuation\">.</span><span class=\"token function\">status</span><span class=\"token punctuation\">(</span><span class=\"token number\">401</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">send</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Token version is invalid'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n  <span class=\"token function\">next</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>In this example, the user’s <code class=\"language-text\">tokenVersion</code> is stored in the database. When a token is revoked, the <code class=\"language-text\">tokenVersion</code> is incremented, and the middleware checks if the presented token is still valid.</p>\n<h3 id=\"user-logout-and-forced-token-invalidation\" style=\"position:relative;\"><a href=\"#user-logout-and-forced-token-invalidation\" aria-label=\"user logout and forced token invalidation permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>User Logout and Forced Token Invalidation</h3>\n<p><strong>How It Works:</strong></p>\n<p>When a user logs out, their JWT token can be invalidated by marking it as such on the server or by expiring the session. This method ensures that the token cannot be used to access protected resources after logout. In systems that support OAuth 2.0 or OpenID Connect, this might involve notifying the identity provider to revoke the token at the source.</p>\n<p><strong>Pros:</strong></p>\n<ul>\n<li><strong>Immediate Effect:</strong> The token is immediately invalidated, providing a prompt security response.</li>\n<li><strong>User-Controlled:</strong> Users can take control of their session’s security by actively logging out.</li>\n</ul>\n<p><strong>Cons:</strong></p>\n<ul>\n<li><strong>Statefulness:</strong> Forced token invalidation requires maintaining a server-side state, which conflicts with the stateless nature of JWTs.</li>\n<li><strong>Implementation Complexity:</strong> Implementing this method can be challenging in systems that rely on stateless JWTs, especially in distributed environments with multiple endpoints.</li>\n</ul>\n<p><strong>Example: User Logout and Forced Token Invalidation in Node.js</strong></p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"35865789848716780000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`const express = require('express');\nconst jwt = require('jwt-simple');\nconst redis = require('redis');\nconst bodyParser = require('body-parser');\nconst nodemailer = require('nodemailer');\nconst app = express();\n\napp.use(bodyParser.json());\nconst redisClient = redis.createClient();\nconst SECRET_KEY = 'your_secret_key'; // Replace with your actual secret key\nconst PORT = 3000;\n\n// Configure email transport for notifications\nconst transporter = nodemailer.createTransport({\n  service: 'gmail',\n  auth: {\n    user: 'your_email@gmail.com', // Replace with your email\n    pass: 'your_email_password'   // Replace with your email password\n  }\n});\n\n// Middleware to verify JWT and check session\nfunction verifyToken(req, res, next) {\n  const token = req.headers['authorization'];\n  if (!token) {\n    return res.status(401).send('No token provided');\n  }\n  try {\n    const decoded = jwt.decode(token, SECRET_KEY);\n    const sessionId = decoded.sessionId;\n    redisClient.get(sessionId, (err, sessionData) => {\n      if (err || !sessionData) {\n        return res.status(401).send('Invalid token');\n      }\n      req.user = decoded; // Attach user info to request\n      next();\n    });\n  } catch (e) {\n    res.status(401).send('Failed to authenticate token');\n  }\n}\n\n// Endpoint for user login (simulated)\napp.post('/login', (req, res) => {\n  const { username, email } = req.body;\n  const sessionId = \\`\\${username}-\\${Date.now()}\\`; // Generate a unique session ID\n  const token = jwt.encode({ sessionId }, SECRET_KEY, 'HS256');\n  redisClient.set(sessionId, JSON.stringify({ username, email }), 'EX', 3600); // Store session with 1-hour expiry\n  res.json({ token });\n});\n\n// Endpoint for user logout\napp.post('/logout', verifyToken, (req, res) => {\n  const sessionId = req.user.sessionId;\n  redisClient.del(sessionId, (err) => {\n    if (err) {\n      return res.status(500).send('Failed to logout');\n    }\n    // Notify user about session expiration\n    redisClient.get(sessionId, (err, sessionData) => {\n      if (!err && sessionData) {\n        const userEmail = JSON.parse(sessionData).email;\n        const mailOptions = {\n          from: 'your_email@gmail.com',\n          to: userEmail,\n          subject: 'Session Expired',\n          text: 'Your session has been terminated. If you did not request this, please contact support.'\n        };\n        transporter.sendMail(mailOptions, (error, info) => {\n          if (error) {\n            console.error('Error sending email:', error);\n          } else {\n            console.log('Email sent:', info.response);\n          }\n        });\n      }\n    });\n    res.send('Logged out successfully');\n  });\n});\n\n// Protected endpoint\napp.get('/protected', verifyToken, (req, res) => {\n  res.send(\\`Hello \\${req.user.sessionId}, you have access to this protected resource\\`);\n});\n\napp.listen(PORT, () => {\n  console.log(\\`Server running on port \\${PORT}\\`);\n});`, `35865789848716780000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"ts\"><pre class=\"language-ts\"><code class=\"language-ts\"><span class=\"token keyword\">const</span> express <span class=\"token operator\">=</span> <span class=\"token keyword\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'express'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> jwt <span class=\"token operator\">=</span> <span class=\"token keyword\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'jwt-simple'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> redis <span class=\"token operator\">=</span> <span class=\"token keyword\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'redis'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> bodyParser <span class=\"token operator\">=</span> <span class=\"token keyword\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'body-parser'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> nodemailer <span class=\"token operator\">=</span> <span class=\"token keyword\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'nodemailer'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> app <span class=\"token operator\">=</span> <span class=\"token function\">express</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\napp<span class=\"token punctuation\">.</span><span class=\"token function\">use</span><span class=\"token punctuation\">(</span>bodyParser<span class=\"token punctuation\">.</span><span class=\"token function\">json</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> redisClient <span class=\"token operator\">=</span> redis<span class=\"token punctuation\">.</span><span class=\"token function\">createClient</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> <span class=\"token constant\">SECRET_KEY</span> <span class=\"token operator\">=</span> <span class=\"token string\">'your_secret_key'</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Replace with your actual secret key</span>\n<span class=\"token keyword\">const</span> <span class=\"token constant\">PORT</span> <span class=\"token operator\">=</span> <span class=\"token number\">3000</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Configure email transport for notifications</span>\n<span class=\"token keyword\">const</span> transporter <span class=\"token operator\">=</span> nodemailer<span class=\"token punctuation\">.</span><span class=\"token function\">createTransport</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  service<span class=\"token operator\">:</span> <span class=\"token string\">'gmail'</span><span class=\"token punctuation\">,</span>\n  auth<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    user<span class=\"token operator\">:</span> <span class=\"token string\">'your_email@gmail.com'</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// Replace with your email</span>\n    pass<span class=\"token operator\">:</span> <span class=\"token string\">'your_email_password'</span>   <span class=\"token comment\">// Replace with your email password</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Middleware to verify JWT and check session</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">verifyToken</span><span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">,</span> res<span class=\"token punctuation\">,</span> next<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> token <span class=\"token operator\">=</span> req<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">[</span><span class=\"token string\">'authorization'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>token<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> res<span class=\"token punctuation\">.</span><span class=\"token function\">status</span><span class=\"token punctuation\">(</span><span class=\"token number\">401</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">send</span><span class=\"token punctuation\">(</span><span class=\"token string\">'No token provided'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n  <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> decoded <span class=\"token operator\">=</span> jwt<span class=\"token punctuation\">.</span><span class=\"token function\">decode</span><span class=\"token punctuation\">(</span>token<span class=\"token punctuation\">,</span> <span class=\"token constant\">SECRET_KEY</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">const</span> sessionId <span class=\"token operator\">=</span> decoded<span class=\"token punctuation\">.</span>sessionId<span class=\"token punctuation\">;</span>\n    redisClient<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span>sessionId<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span>err<span class=\"token punctuation\">,</span> sessionData<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>err <span class=\"token operator\">||</span> <span class=\"token operator\">!</span>sessionData<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">return</span> res<span class=\"token punctuation\">.</span><span class=\"token function\">status</span><span class=\"token punctuation\">(</span><span class=\"token number\">401</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">send</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Invalid token'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token punctuation\">}</span>\n      req<span class=\"token punctuation\">.</span>user <span class=\"token operator\">=</span> decoded<span class=\"token punctuation\">;</span> <span class=\"token comment\">// Attach user info to request</span>\n      <span class=\"token function\">next</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    res<span class=\"token punctuation\">.</span><span class=\"token function\">status</span><span class=\"token punctuation\">(</span><span class=\"token number\">401</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">send</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Failed to authenticate token'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token comment\">// Endpoint for user login (simulated)</span>\napp<span class=\"token punctuation\">.</span><span class=\"token function\">post</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/login'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">,</span> res<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> username<span class=\"token punctuation\">,</span> email <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> req<span class=\"token punctuation\">.</span>body<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> sessionId <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>username<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">-</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>Date<span class=\"token punctuation\">.</span><span class=\"token function\">now</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Generate a unique session ID</span>\n  <span class=\"token keyword\">const</span> token <span class=\"token operator\">=</span> jwt<span class=\"token punctuation\">.</span><span class=\"token function\">encode</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> sessionId <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">SECRET_KEY</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'HS256'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  redisClient<span class=\"token punctuation\">.</span><span class=\"token function\">set</span><span class=\"token punctuation\">(</span>sessionId<span class=\"token punctuation\">,</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> username<span class=\"token punctuation\">,</span> email <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'EX'</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3600</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Store session with 1-hour expiry</span>\n  res<span class=\"token punctuation\">.</span><span class=\"token function\">json</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> token <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Endpoint for user logout</span>\napp<span class=\"token punctuation\">.</span><span class=\"token function\">post</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/logout'</span><span class=\"token punctuation\">,</span> verifyToken<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">,</span> res<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> sessionId <span class=\"token operator\">=</span> req<span class=\"token punctuation\">.</span>user<span class=\"token punctuation\">.</span>sessionId<span class=\"token punctuation\">;</span>\n  redisClient<span class=\"token punctuation\">.</span><span class=\"token function\">del</span><span class=\"token punctuation\">(</span>sessionId<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span>err<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>err<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">return</span> res<span class=\"token punctuation\">.</span><span class=\"token function\">status</span><span class=\"token punctuation\">(</span><span class=\"token number\">500</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">send</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Failed to logout'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token comment\">// Notify user about session expiration</span>\n    redisClient<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span>sessionId<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span>err<span class=\"token punctuation\">,</span> sessionData<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>err <span class=\"token operator\">&amp;&amp;</span> sessionData<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">const</span> userEmail <span class=\"token operator\">=</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">parse</span><span class=\"token punctuation\">(</span>sessionData<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>email<span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">const</span> mailOptions <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n          from<span class=\"token operator\">:</span> <span class=\"token string\">'your_email@gmail.com'</span><span class=\"token punctuation\">,</span>\n          to<span class=\"token operator\">:</span> userEmail<span class=\"token punctuation\">,</span>\n          subject<span class=\"token operator\">:</span> <span class=\"token string\">'Session Expired'</span><span class=\"token punctuation\">,</span>\n          text<span class=\"token operator\">:</span> <span class=\"token string\">'Your session has been terminated. If you did not request this, please contact support.'</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n        transporter<span class=\"token punctuation\">.</span><span class=\"token function\">sendMail</span><span class=\"token punctuation\">(</span>mailOptions<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span>error<span class=\"token punctuation\">,</span> info<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n          <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>error<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n            <span class=\"token builtin\">console</span><span class=\"token punctuation\">.</span><span class=\"token function\">error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Error sending email:'</span><span class=\"token punctuation\">,</span> error<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n          <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n            <span class=\"token builtin\">console</span><span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Email sent:'</span><span class=\"token punctuation\">,</span> info<span class=\"token punctuation\">.</span>response<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n          <span class=\"token punctuation\">}</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    res<span class=\"token punctuation\">.</span><span class=\"token function\">send</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Logged out successfully'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Protected endpoint</span>\napp<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/protected'</span><span class=\"token punctuation\">,</span> verifyToken<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">,</span> res<span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  res<span class=\"token punctuation\">.</span><span class=\"token function\">send</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">Hello </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>req<span class=\"token punctuation\">.</span>user<span class=\"token punctuation\">.</span>sessionId<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">, you have access to this protected resource</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\napp<span class=\"token punctuation\">.</span><span class=\"token function\">listen</span><span class=\"token punctuation\">(</span><span class=\"token constant\">PORT</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token builtin\">console</span><span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">Server running on port </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token constant\">PORT</span><span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<h3 id=\"token-revocation-lists\" style=\"position:relative;\"><a href=\"#token-revocation-lists\" aria-label=\"token revocation lists permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Token Revocation Lists</h3>\n<p><strong>How It Works:</strong></p>\n<p>A Token Revocation List (TRL) operates similarly to a blacklist but is often implemented as a centralized or distributed service that can be queried to determine if a token has been revoked. This method is especially effective in large-scale distributed systems where multiple services and endpoints need to recognize and enforce token revocation.</p>\n<p><strong>Pros:</strong></p>\n<ul>\n<li><strong>Scalability:</strong> A TRL can be designed to handle high loads in distributed environments, ensuring that all services consistently enforce token revocation.</li>\n<li><strong>Centralized Management:</strong> By centralizing token revocation, this method simplifies the management and enforcement of revocation policies.</li>\n</ul>\n<p><strong>Cons:</strong></p>\n<ul>\n<li><strong>Latency:</strong> Querying a TRL can introduce latency, especially if the revocation list is not stored in an in-memory database or is not optimized for fast lookups.</li>\n<li><strong>Complexity:</strong> Implementing and maintaining a TRL requires careful design to ensure scalability and reliability across distributed services.</li>\n</ul>\n<p><strong>Implementation Tip:</strong></p>\n<p>When designing a TRL, consider using in-memory data stores like Redis or distributed caching systems to reduce latency. Additionally, ensure that your system can handle large-scale requests by implementing load balancing and failover mechanisms.</p>\n<p><strong>Example of Implementing a Simple TRL in Node.js:</strong></p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"68933320570225520000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`let trustedRevocationList = [];\n\nfunction updateRevocationList(newList) {\n  trustedRevocationList = newList;\n}\n\nfunction isTokenRevoked(jti) {\n  return trustedRevocationList.includes(jti);\n}\n\n// Middleware to check TRL\nfunction checkRevocationList(req, res, next) {\n  const token = req.headers['authorization'];\n  const decoded = jwt.verify(token, process.env.JWT_SECRET);\n\n  if (isTokenRevoked(decoded.jti)) {\n    return res.status(401).send('Token has been revoked');\n  }\n  next();\n}\n\n// Example of updating TRL (this would typically be done periodically)\nsetInterval(() => {\n  // Fetch the latest TRL from a trusted source\n  const latestTRL = fetchTrustedRevocationList();\n  updateRevocationList(latestTRL);\n}, 60000); // Update every 60 seconds`, `68933320570225520000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"ts\"><pre class=\"language-ts\"><code class=\"language-ts\"><span class=\"token keyword\">let</span> trustedRevocationList <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">updateRevocationList</span><span class=\"token punctuation\">(</span>newList<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  trustedRevocationList <span class=\"token operator\">=</span> newList<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">isTokenRevoked</span><span class=\"token punctuation\">(</span>jti<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">return</span> trustedRevocationList<span class=\"token punctuation\">.</span><span class=\"token function\">includes</span><span class=\"token punctuation\">(</span>jti<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token comment\">// Middleware to check TRL</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">checkRevocationList</span><span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">,</span> res<span class=\"token punctuation\">,</span> next<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> token <span class=\"token operator\">=</span> req<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">[</span><span class=\"token string\">'authorization'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> decoded <span class=\"token operator\">=</span> jwt<span class=\"token punctuation\">.</span><span class=\"token function\">verify</span><span class=\"token punctuation\">(</span>token<span class=\"token punctuation\">,</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">JWT_SECRET</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">isTokenRevoked</span><span class=\"token punctuation\">(</span>decoded<span class=\"token punctuation\">.</span>jti<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> res<span class=\"token punctuation\">.</span><span class=\"token function\">status</span><span class=\"token punctuation\">(</span><span class=\"token number\">401</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">send</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Token has been revoked'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n  <span class=\"token function\">next</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token comment\">// Example of updating TRL (this would typically be done periodically)</span>\n<span class=\"token function\">setInterval</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// Fetch the latest TRL from a trusted source</span>\n  <span class=\"token keyword\">const</span> latestTRL <span class=\"token operator\">=</span> <span class=\"token function\">fetchTrustedRevocationList</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token function\">updateRevocationList</span><span class=\"token punctuation\">(</span>latestTRL<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token number\">60000</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Update every 60 seconds</span></code></pre></div>\n<h3 id=\"refresh-tokens-for-long-lived-sessions\" style=\"position:relative;\"><a href=\"#refresh-tokens-for-long-lived-sessions\" aria-label=\"refresh tokens for long lived sessions permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Refresh Tokens for Long-Lived Sessions</h3>\n<p><strong>How It Works:</strong></p>\n<p>In scenarios where long-lived sessions are necessary, using refresh tokens in conjunction with JWTs provides a secure way to manage token expiry and revocation. The refresh token is stored securely on the server and is used to generate new JWT access tokens when the previous one expires. If a user’s account is compromised, the refresh token can be revoked, preventing the issuance of new JWT access tokens.</p>\n<p><strong>Pros:</strong></p>\n<ul>\n<li><strong>Increased Security:</strong> This method enhances security by limiting the lifespan of JWT access tokens while providing a mechanism for immediate revocation through the refresh token.</li>\n<li><strong>Flexible Control:</strong> Allows for the revocation of individual sessions without affecting others, providing a granular approach to session management.</li>\n</ul>\n<p><strong>Cons:</strong></p>\n<ul>\n<li><strong>Complexity:</strong> Managing refresh tokens adds complexity to the backend and client-side logic, as well as potential storage challenges if multiple refresh tokens are issued.</li>\n<li><strong>No Immediate Revocation for Access Tokens:</strong> Revoking the refresh token does not immediately invalidate the existing JWT access token, leaving a short window of vulnerability.</li>\n</ul>\n<p><strong>Example in Node.js:</strong></p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"313376420683075800\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"Copied!\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`const jwt = require('jsonwebtoken');\nconst uuid = require('uuid');\n\n// Simulated in-memory refresh token store\nlet refreshTokenStore = {};\n\nfunction generateToken(user) {\n  const payload = { userId: user.id };\n  const accessToken = jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '15m' });\n  const refreshToken = uuid.v4();\n\n  // Store refresh token server-side\n  refreshTokenStore[refreshToken] = user.id;\n\n  return { accessToken, refreshToken };\n}\n\nfunction refreshAccessToken(refreshToken) {\n  const userId = refreshTokenStore[refreshToken];\n  if (!userId) {\n    throw new Error('Invalid refresh token');\n  }\n\n  const newAccessToken = jwt.sign({ userId }, process.env.JWT_SECRET, { expiresIn: '15m' });\n  return newAccessToken;\n}\n\nfunction revokeRefreshToken(refreshToken) {\n  delete refreshTokenStore[refreshToken];\n}\n\n// Middleware example for refreshing access tokens\nfunction refreshTokenMiddleware(req, res, next) {\n  const { refreshToken } = req.body;\n\n  try {\n    const newAccessToken = refreshAccessToken(refreshToken);\n    res.json({ accessToken: newAccessToken });\n  } catch (err) {\n    res.status(401).send('Invalid or expired refresh token');\n  }\n}`, `313376420683075800`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                <svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"ts\"><pre class=\"language-ts\"><code class=\"language-ts\"><span class=\"token keyword\">const</span> jwt <span class=\"token operator\">=</span> <span class=\"token keyword\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'jsonwebtoken'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> uuid <span class=\"token operator\">=</span> <span class=\"token keyword\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'uuid'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Simulated in-memory refresh token store</span>\n<span class=\"token keyword\">let</span> refreshTokenStore <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">generateToken</span><span class=\"token punctuation\">(</span>user<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> payload <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> userId<span class=\"token operator\">:</span> user<span class=\"token punctuation\">.</span>id <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> accessToken <span class=\"token operator\">=</span> jwt<span class=\"token punctuation\">.</span><span class=\"token function\">sign</span><span class=\"token punctuation\">(</span>payload<span class=\"token punctuation\">,</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">JWT_SECRET</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> expiresIn<span class=\"token operator\">:</span> <span class=\"token string\">'15m'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> refreshToken <span class=\"token operator\">=</span> uuid<span class=\"token punctuation\">.</span><span class=\"token function\">v4</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Store refresh token server-side</span>\n  refreshTokenStore<span class=\"token punctuation\">[</span>refreshToken<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> user<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">{</span> accessToken<span class=\"token punctuation\">,</span> refreshToken <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">refreshAccessToken</span><span class=\"token punctuation\">(</span>refreshToken<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> userId <span class=\"token operator\">=</span> refreshTokenStore<span class=\"token punctuation\">[</span>refreshToken<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>userId<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Invalid refresh token'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">const</span> newAccessToken <span class=\"token operator\">=</span> jwt<span class=\"token punctuation\">.</span><span class=\"token function\">sign</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> userId <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">JWT_SECRET</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> expiresIn<span class=\"token operator\">:</span> <span class=\"token string\">'15m'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">return</span> newAccessToken<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">revokeRefreshToken</span><span class=\"token punctuation\">(</span>refreshToken<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">delete</span> refreshTokenStore<span class=\"token punctuation\">[</span>refreshToken<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token comment\">// Middleware example for refreshing access tokens</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">refreshTokenMiddleware</span><span class=\"token punctuation\">(</span>req<span class=\"token punctuation\">,</span> res<span class=\"token punctuation\">,</span> next<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> refreshToken <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> req<span class=\"token punctuation\">.</span>body<span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> newAccessToken <span class=\"token operator\">=</span> <span class=\"token function\">refreshAccessToken</span><span class=\"token punctuation\">(</span>refreshToken<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    res<span class=\"token punctuation\">.</span><span class=\"token function\">json</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> accessToken<span class=\"token operator\">:</span> newAccessToken <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span>err<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    res<span class=\"token punctuation\">.</span><span class=\"token function\">status</span><span class=\"token punctuation\">(</span><span class=\"token number\">401</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">send</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Invalid or expired refresh token'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h2 id=\"how-to-make-access-token-management-easier\" style=\"position:relative;\"><a href=\"#how-to-make-access-token-management-easier\" aria-label=\"how to make access token management easier permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How to Make Access Token Management Easier</h2>\n<p>Effective access token management is crucial for maintaining the security of your application. Here are some best practices to simplify the process:</p>\n<ul>\n<li><strong>Use Refresh Tokens:</strong> As mentioned, refresh tokens can provide an effective way to manage and revoke JWTs. Ensure they are securely stored, either on the client-side or in Redis, and frequently rotated to prevent misuse.</li>\n<li><strong>Minimize Token Lifespan:</strong> Short-lived tokens reduce the impact of a compromised token. Pair them with refresh tokens to balance security and usability, configuring the <code class=\"language-text\">exp</code> parameter appropriately.</li>\n<li><strong>Ensure Secure Storage:</strong> Store tokens securely, whether in cookies with the <code class=\"language-text\">HttpOnly</code> and <code class=\"language-text\">Secure</code> flags or in secure client-side storage mechanisms like local storage.</li>\n<li><strong>Monitor for Suspicious Activity:</strong> Implement monitoring and notifications for unusual token usage patterns, such as tokens being used from multiple locations.</li>\n<li><strong>Automate Token Management:</strong> Use tools like SuperTokens to handle JWT creation, validation, and revocation. This can streamline your authentication process and reduce the risk of errors.</li>\n</ul>\n<p>For more on creating JWTs and securing user sessions, see our <a href=\"https://supertokens.com/docs/microservice_auth/jwt-creation\" target=\"_blank\" rel=\"nofollow\">docs on JWT Creation</a> and our guide on <a href=\"https://supertokens.com/blog/are-you-using-jwts-for-user-sessions-in-the-correct-way\" target=\"_blank\" rel=\"nofollow\">Using JWTs for User Sessions</a>. You can also explore how to configure secure tokens in Node.js with backend tools like Redis for in-memory storage.</p>\n<h2 id=\"risks-of-improper-access-token-management\" style=\"position:relative;\"><a href=\"#risks-of-improper-access-token-management\" aria-label=\"risks of improper access token management permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Risks of Improper Access Token Management</h2>\n<p>Failing to properly manage and revoke JWT tokens can lead to serious security risks:</p>\n<ul>\n<li><strong>Unauthorized Access:</strong> Compromised tokens can grant unauthorized access to your application, leading to data breaches and other security incidents.</li>\n<li><strong>Token Theft:</strong> If tokens are not securely stored on the client-side, they can be stolen and used maliciously.</li>\n<li><strong>Replay Attacks:</strong> Attackers can reuse a stolen token to gain unauthorized access if tokens are not properly managed.</li>\n<li><strong>Poor User Experience:</strong> Improper token management can lead to unnecessary logouts or difficulties accessing services.</li>\n<li><strong>Legal Implications:</strong> In regulated industries like fintech, failing to manage tokens properly can result in compliance violations, leading to legal penalties.</li>\n</ul>\n<p>For a comprehensive guide on implementing secure authentication practices, check out our articles on <a href=\"https://supertokens.com/blog/oauth-vs-jwt\" target=\"_blank\" rel=\"nofollow\">OAuth 2.0 vs. JWT</a> and <a href=\"https://supertokens.com/blog/a-guide-to-implementing-passwordless-login\" target=\"_blank\" rel=\"nofollow\">Passwordless Login</a>. You can also find code examples on GitHub for integrating these practices in your Node.js applications.</p>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>Revoking JWT tokens is a crucial aspect of securing modern web applications. While the stateless nature of JWTs presents challenges, the methods discussed above offer effective strategies for maintaining secure access management. Whether through token blacklisting, rotating secrets, or using refresh tokens, implementing a robust revocation strategy is essential to protecting your application and users’ data.</p>\n<p>There are a ton of intricacies while building a robust authentication solution with JWTs. Keeping up with best practices and the most secure standards, while keeping up-to-date with the latest threat vectors, is hard to say the least.</p>\n<p>Unless you’re building a personal project, learning, or have an extremely niche use case that is not supported by auth providers, it is better to offload the headache to a service instead.</p>\n<p>Easily manage user access with <a href=\"https://supertokens.com/product\" target=\"_blank\" rel=\"nofollow\">SuperTokens</a> and take the hassle out of JWT management. Start securing your application today.</p>","frontmatter":{"date":"August 15, 2024","title":"7 Ways To Revoke JWT Tokens","cover":"revoking-access-with-a-jwt-blacklist.png","author":"Dejan Lukic","description":"Learn how to maintain a JWT token blacklist / deny list using an in-memory data cache"},"fields":{"slug":"/revoking-access-with-a-jwt-blacklist/"}},"site":{"siteMetadata":{"title":"SuperTokens Blog"}}},"pageContext":{"id":"83363a09-8990-5fc8-8d35-01d24bb3d4d5","fields__slug":"/revoking-access-with-a-jwt-blacklist/","__params":{"fields__slug":"revoking-access-with-a-jwt-blacklist"}}},
    "staticQueryHashes": []}