<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nikhil Sai</title>
    <description>The latest articles on DEV Community by Nikhil Sai (@nikhil_sai_3afd19da0e90db).</description>
    <link>https://dev.to/nikhil_sai_3afd19da0e90db</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3421166%2F2d9fc0f0-4123-4627-8d49-eef2e2b86da8.jpg</url>
      <title>DEV Community: Nikhil Sai</title>
      <link>https://dev.to/nikhil_sai_3afd19da0e90db</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nikhil_sai_3afd19da0e90db"/>
    <language>en</language>
    <item>
      <title>JWT Debugging: 5 Tasks You'll Hit Daily (and How to Handle Them Without a Library)</title>
      <dc:creator>Nikhil Sai</dc:creator>
      <pubDate>Tue, 28 Jul 2026 18:30:00 +0000</pubDate>
      <link>https://dev.to/nikhil_sai_3afd19da0e90db/jwt-debugging-5-tasks-youll-hit-daily-and-how-to-handle-them-without-a-library-3f69</link>
      <guid>https://dev.to/nikhil_sai_3afd19da0e90db/jwt-debugging-5-tasks-youll-hit-daily-and-how-to-handle-them-without-a-library-3f69</guid>
      <description>&lt;p&gt;JWTs show up everywhere: auth headers, session cookies, API gateways and debugging them usually means someone pasting a token into a random website and hoping it's not logging it. Here are five recurring JWT tasks worth having a fast, trustworthy way to handle.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Decoding header and payload
&lt;/h2&gt;

&lt;p&gt;A JWT is just three Base64URL-encoded segments joined by dots header, payload, signature. You don't need a library or an online tool of questionable trustworthiness to read one; you just need something that splits it and renders the header and payload as readable JSON.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;decodeJwt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;headerB64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payloadB64&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;atob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/-/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/_/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;headerB64&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payloadB64&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's genuinely all a "JWT decoder" does under the hood no signature verification, just structural decoding. Worth knowing so you're never surprised by what one of these tools can and can't tell you.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Checking expiry without doing the math
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;exp&lt;/code&gt; claim is a Unix timestamp, and mentally converting something like &lt;code&gt;1785340800&lt;/code&gt; into a date is not a good use of anyone's time. Once decoded, &lt;code&gt;new Date(payload.exp * 1000)&lt;/code&gt; gets you there but if you're doing this often, having &lt;code&gt;exp&lt;/code&gt;, &lt;code&gt;iat&lt;/code&gt;, and &lt;code&gt;nbf&lt;/code&gt; rendered as human-readable dates next to the raw value saves the mental math every single time.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Spotting algorithm mismatches
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;alg&lt;/code&gt; field in the header (&lt;code&gt;HS256&lt;/code&gt;, &lt;code&gt;RS256&lt;/code&gt;, &lt;code&gt;none&lt;/code&gt;) is a classic attack surface a server that trusts the client-supplied algorithm is vulnerable to &lt;code&gt;alg: none&lt;/code&gt; forgery. If you're ever debugging why a token verification is behaving unexpectedly, checking the decoded header's &lt;code&gt;alg&lt;/code&gt; field first is a fast sanity check before diving into signature logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Inspecting custom claims
&lt;/h2&gt;

&lt;p&gt;Most tokens carry more than &lt;code&gt;sub&lt;/code&gt; and &lt;code&gt;exp&lt;/code&gt; roles, tenant IDs, scopes, feature flags. When a permissions bug shows up in production, decoding the &lt;em&gt;actual&lt;/em&gt; token a user has (not the one you assume they have) is usually the fastest way to confirm what's wrong. This is the debugging step people skip most often, and it's the one that actually resolves the bug fastest.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Verifying structure before debugging further
&lt;/h2&gt;

&lt;p&gt;"Invalid token" errors are often just malformed input a truncated copy-paste, a missing segment, extra whitespace. Decoding first tells you immediately whether you're dealing with a structurally broken token or a genuine signature/claims problem downstream.&lt;/p&gt;

&lt;h2&gt;
  
  
  The privacy angle nobody thinks about until it bites them
&lt;/h2&gt;

&lt;p&gt;Here's the thing about JWTs specifically: they often carry live session data, and pasting a production token into a random "jwt decoder" website means that site's server sees your token, even if only in transit. Most of these sites aren't malicious, but you genuinely can't verify that from the UI.&lt;/p&gt;

&lt;p&gt;I ended up building a &lt;a href="https://simpledevtools.org/tools/jwt-decoder" rel="noopener noreferrer"&gt;JWT Decoder&lt;/a&gt; that runs entirely client-side for exactly this reason you can open dev tools, check the network tab, and confirm nothing gets sent anywhere. It's part of a broader set of ~49 browser-based dev utilities I've been building at &lt;a href="https://simpledevtools.org" rel="noopener noreferrer"&gt;Simple Dev Tools&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick checklist before you trust a JWT
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Decode header + payload, confirm &lt;code&gt;alg&lt;/code&gt; matches what your server expects&lt;/li&gt;
&lt;li&gt;Check &lt;code&gt;exp&lt;/code&gt; hasn't passed and &lt;code&gt;nbf&lt;/code&gt; has&lt;/li&gt;
&lt;li&gt;Confirm claims match the identity/permissions you expect&lt;/li&gt;
&lt;li&gt;Never decode a production token on a site you don't control&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://simpledevtools.org/blog/5-jwt-debugging-tasks-every-developer-should-bookmark" rel="noopener noreferrer"&gt;simpledevtools.org/blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>debugging</category>
      <category>javascript</category>
      <category>security</category>
    </item>
  </channel>
</rss>
