<?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: Avada Labs</title>
    <description>The latest articles on DEV Community by Avada Labs (@avadalabs).</description>
    <link>https://dev.to/avadalabs</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%2F4241072%2Fe8ba33eb-5c16-482c-b7d5-10ab3a6f2cc0.png</url>
      <title>DEV Community: Avada Labs</title>
      <link>https://dev.to/avadalabs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/avadalabs"/>
    <language>en</language>
    <item>
      <title>Free JWT Secret Key Generator | Secure HS256, HS384, HS512 Keys Online</title>
      <dc:creator>Avada Labs</dc:creator>
      <pubDate>Thu, 12 Nov 2026 12:43:04 +0000</pubDate>
      <link>https://dev.to/avadalabs/your-jwt-secret-is-probably-too-short-1boo</link>
      <guid>https://dev.to/avadalabs/your-jwt-secret-is-probably-too-short-1boo</guid>
      <description>&lt;p&gt;Hi DEV, this is my first post. I'm a developer who builds websites, WordPress projects and browser extensions, and the topic comes from something I kept running into: JWT secrets that are far too weak.&lt;/p&gt;

&lt;p&gt;The rule most people never read&lt;/p&gt;

&lt;p&gt;If you sign tokens with HS256, the secret has to be at least as long as the hash output. That is 256 bits, or 32 bytes. This is not a tip, it is in the spec. RFC 7518, section 3.2, says a key of the same size as the hash output or larger MUST be used with HMAC-SHA2 algorithms.&lt;/p&gt;

&lt;p&gt;So the same rule applies to the others:&lt;/p&gt;

&lt;p&gt;Algorithm   Minimum secret&lt;br&gt;
HS256   256 bits (32 bytes)&lt;br&gt;
HS384   384 bits (48 bytes)&lt;br&gt;
HS512   512 bits (64 bytes)&lt;br&gt;
Why a short secret is a real problem&lt;/p&gt;

&lt;p&gt;A JWT is signed, not encrypted. Anyone who sees a token can copy it and try guessing the secret offline, as many times as they like, with no rate limit. Tools like hashcat have a mode just for this (-m 16500).&lt;/p&gt;

&lt;p&gt;If your secret is secret, changeme or your app's name, it falls in seconds to a normal wordlist. Once someone has the secret, they can sign any token they want, including one that says they are an admin.&lt;/p&gt;

&lt;p&gt;Length is not the same as strength&lt;/p&gt;

&lt;p&gt;This confuses a lot of people. A 64-character hex string looks long, but it only holds 32 bytes of randomness. Those 256 bits are the real strength, not the number of characters. And a long password you typed yourself is still weaker than 32 random bytes, because humans are predictable.&lt;/p&gt;

&lt;p&gt;The secret should come from a cryptographically secure random generator, not from your head.&lt;/p&gt;

&lt;p&gt;How to generate one&lt;/p&gt;

&lt;p&gt;Pick whatever you already have installed:&lt;/p&gt;

&lt;p&gt;bash&lt;/p&gt;

&lt;h1&gt;
  
  
  OpenSSL
&lt;/h1&gt;

&lt;p&gt;openssl rand -hex 32&lt;br&gt;
js&lt;br&gt;
// Node.js&lt;br&gt;
require('crypto').randomBytes(32).toString('hex');&lt;br&gt;
python&lt;/p&gt;

&lt;h1&gt;
  
  
  Python
&lt;/h1&gt;

&lt;p&gt;import secrets&lt;br&gt;
secrets.token_hex(32)&lt;/p&gt;

&lt;p&gt;All three give you 256 bits of randomness.&lt;/p&gt;

&lt;p&gt;What to do with it&lt;/p&gt;

&lt;p&gt;Put it in an environment variable and read it from there:&lt;/p&gt;

&lt;p&gt;bash&lt;br&gt;
JWT_SECRET=your-generated-value&lt;br&gt;
Never commit it to Git. If it was ever committed, treat it as leaked and replace it.&lt;br&gt;
Use a different secret for each environment (development, staging, production).&lt;br&gt;
Plan for rotation. Changing the secret logs everyone out, so decide how you will handle that before you need to.&lt;br&gt;
Two more mistakes worth fixing&lt;/p&gt;

&lt;p&gt;Pin the algorithm when you verify. Do not let the token decide how it should be checked:&lt;/p&gt;

&lt;p&gt;js&lt;br&gt;
jwt.verify(token, process.env.JWT_SECRET, { algorithms: ['HS256'] });&lt;/p&gt;

&lt;p&gt;Decoding is not verifying. Reading the header and payload of a token tells you nothing about whether it is real. Only checking the signature with your secret does.&lt;/p&gt;

&lt;p&gt;A small tool I made for this&lt;/p&gt;

&lt;p&gt;I got tired of pasting secrets and tokens into random websites, so I built a free tool that generates HS256, HS384 and HS512 secrets and decodes tokens, all inside your browser with the Web Crypto API. Nothing is uploaded: &lt;a href="https://jwtsecretkey.com/" rel="noopener noreferrer"&gt;jwtsecretkey.com&lt;br&gt;
&lt;/a&gt;&lt;br&gt;
If you use something different, that is fine. The point is the same: 32 random bytes, kept out of your repo.&lt;/p&gt;

&lt;p&gt;What is the weakest JWT secret you have ever found in a real project? I would like to hear it.&lt;/p&gt;

</description>
      <category>jwt</category>
      <category>security</category>
      <category>webdev</category>
      <category>node</category>
    </item>
  </channel>
</rss>
