How to Generate a Strong JWT Secret Key

Hint: it's not typing random characters and hoping for the best. Here's what actually works.

When I first set up JWT in my app, I opened my .env file, typed a bunch of random-looking characters, and moved on. Felt fine. Took five seconds.

A few weeks later I found out that's one of the worst things you can do.

Here's what I wish someone had told me from the start.

First, What Even Is a JWT Secret Key?

When your server creates a JWT token, it needs to sign it. That signature is what proves the token is real and hasn't been changed by anyone.

Your secret key is what creates that signature. If someone gets your key, they can make fake tokens that look completely real. They can log in as any user, including your admins.

So yeah. It matters.

Why Typing It Yourself Doesn't Work

I know it feels random when you mash the keyboard. But it really isn't.

Your brain picks patterns without you even noticing. You hit keys near your home row more often. You avoid symbols because they're annoying to reach. You use the same hand movements you've used a hundred times before.

Not exactly random. Not exactly safe.

Here's the thing — hackers know exactly how humans type when they're trying to be random. They build tools around those patterns. What feels chaotic to you is actually pretty predictable to someone trying to break in.

What About Just Using Math.random()?

If you've ever done something like this:

const secret = Math.random().toString(36).substring(2);

Stop. Please.

Math.random() is what developers call pseudo-random. It looks random, but under the hood it's just a formula running calculations. If someone figures out the starting value (the "seed"), they can predict every number that comes out of it.

Think of it like a magic trick. It looks impressive until you know how it's done. Then it's obvious.

For security, you need something that can't be predicted. Ever. Even if someone knows exactly how your code works.

Entropy: What It Is and Why You Should Care

You'll see this word come up a lot in security talk. It sounds fancy but the idea is simple.

Entropy just means how unpredictable something is.

Picture a bucket with 4 balls in it — red, blue, green, yellow. If I reach in without looking, you could probably guess what I pull out pretty quickly. Low entropy. Not many possibilities.

Now picture a bucket with 10,000 balls in every shade of every color. Good luck guessing. That's high entropy.

Your JWT secret key needs to be that second bucket. So many possible combinations that guessing it is basically impossible.

A good key should be at least 256 bits long. That means roughly 10^77 possible combinations. To put that in perspective, there are about 10^80 atoms in the observable universe. We're talking similar numbers.

Nobody's guessing that.

So How Do Machines Actually Get Real Randomness?

This is the part that blew my mind a little.

Computers can pull randomness from genuinely unpredictable physical sources. Things like:

  • Tiny electrical noise inside your hardware
  • The exact timing between your keystrokes
  • Fluctuations in your CPU temperature
  • Mouse movement timing down to the microsecond

None of that can be predicted or reproduced. That's what cryptographically secure random generators use as their source.

The result is actual randomness. Not "looks random to a human" randomness. Real, mathematical, cryptographic randomness.

Your keyboard smashing cannot compete with that.

Three Ways to Generate a Proper Key

Option 1: Use a Terminal Command

If you're on Mac or Linux, open your terminal and run this:

openssl rand -hex 32

That gives you 32 bytes of cryptographically secure random data as a 64-character hex string. Copy it straight into your .env file. Done.

On Windows you can use Node.js instead:

node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

Both of these use your operating system's built-in secure random generator. They're solid options.

Option 2: Use Node's Crypto Module in Your Code

If you want to generate keys programmatically, Node.js has a built-in crypto module that's actually secure:

const crypto = require('crypto'); const secret = crypto.randomBytes(32).toString('hex'); console.log(secret);

This is the right way to do it in code. Not Math.random(). Not a custom formula. The built-in crypto module.

Option 3: Just Use a Generator

Honestly this is what I do most of the time now. When I'm setting up a new project, I just go to jwtsecretkeygenerator.com, click generate, and copy the key.

It's fast. It uses proper cryptographic randomness under the hood. And I don't have to open a terminal or remember any commands.

No account needed, nothing to install. Just a key ready to use in about three seconds.

How Long Should Your Key Actually Be?

Short answer: at least 256 bits. That's 32 bytes, which gives you a 64-character hex string.

Some people use 512 bits for extra peace of mind. That's fine too. More bits = more entropy = harder to crack.

Just don't go below 256. Anything shorter and you're cutting corners on security for basically no reason.

💡 Quick Rule: If your key is shorter than 32 characters, it's not long enough. If you can remember it without looking, it's not random enough. If it contains any real words, start over.

Where to Store It Once You Have It

This is just as important as generating it right.

  • Store it in a .env file, never in your actual code
  • Add .env to your .gitignore immediately
  • Never paste it into a chat, email, or document
  • Use different keys for development and production
  • If you accidentally expose it, generate a new one right away

A perfectly random key stored carelessly is still a vulnerability. Treat it like a password to your entire user database. Because that's basically what it is.

What a Bad Key Looks Like vs a Good One

Here are some real examples of the difference:

Bad keys (yes, people actually use these):

secret mysecretkey jwt_secret_key myapp2026 asdfghjklasdfghjkl

Good key (generated properly):

a3f8c2d1e7b9044f2c68a5d3e1f7b290c4a8e6d2f0b1c3a5e7d9f2b4c6a8e0d3

See how the good one looks like complete nonsense? That's exactly what you want. No patterns, no words, no recognizable structure.

If your key makes any kind of sense to you, it's not good enough.

One Last Thing

Generating a strong key is the easy part. It takes about 10 seconds with the right tool.

Most developers skip it because it feels like a small detail. It isn't. Your entire authentication system rests on that one key being unpredictable.

So do it right the first time. Generate it properly, store it safely, and then forget about it. Let it do its job quietly in the background while you focus on building the actual app.

That's the whole point of using the right tool for the job.