BlogJWT Brute Force Attacks: How They Work and How to Stop Them
·Updated July 22, 2026·5 min read·JWTSecrets Team

JWT Brute Force Attacks: How They Work and How to Stop Them

Learn how offline JWT brute force attacks crack weak HMAC secrets, how fast GPUs try candidates, and how to generate secrets that cannot be cracked.

JWT Brute Force Is an Offline Attack

JWT brute force attacks are not theoretical. Researchers have published databases of common JWT secrets found in production applications. If your secret is short, human-readable, or copied from a tutorial, it may already be in those databases — and cracking it does not require hitting your API at all.

This post explains how offline HMAC cracking works, how fast modern hardware tries candidates, which secret shapes fail immediately, and how to generate secrets that remain out of reach. Use the JWT Secret Generator when you need a browser CSPRNG, then store the result outside source control.

How JWT Brute Force Works

A JWT consists of three base64url-encoded segments: header.payload.signature. For HS256, the signature is an HMAC — a keyed hash of header + "." + payload using your secret.

An attacker who intercepts a valid JWT can attempt to crack the secret offline:

1. Extract the header and payload (base64url-decode them for inspection; keep the raw signing input for HMAC).

2. Try candidate secrets from a wordlist or ruleset.

3. For each candidate, compute HMAC-SHA256(candidate, header + "." + payload).

4. If the result matches the token's signature, the candidate is the real secret.

This requires no server access, no rate limiting, and no detection on your side. Compute happens on the attacker's hardware. Once the secret falls, every token can be forged until you rotate.

Validate unfamiliar tokens with the JWT Validator during investigations — but remember validation with the real secret is not the same as resisting offline search.

Attack Speed on Modern Hardware

HardwareHS256 Attempts/Second
Consumer CPU (single core)~50,000
Consumer CPU (multi-core)~500,000
Consumer GPU (RTX 4090)~200,000,000
Cloud GPU cluster (8x A100)~2,000,000,000

Dictionary and rule-based attacks are far faster than pure brute force against short human strings. Hashcat and jwtcrack-style tooling make this accessible to hobbyists, not only nation-states.

Time to Crack by Secret Type

SecretEntropyTime to Crack (GPU cluster)
`"secret"`~40 bitsMilliseconds (dictionary)
`"myapp_jwt_2024"`~50 bitsMinutes (rule-based attack)
8-char alphanumeric~47 bitsHours
16-char alphanumeric~95 bitsYears
256-bit CSPRNG hex256 bitsLonger than the age of the universe

The formula for exhaustive search is T = S / H where S is the search space (2^entropy_bits) and H is the hash rate. At roughly 2 × 10^9 attempts per second against a true 256-bit random secret: T = 2^256 / 2×10^9 ≈ 5.8 × 10^67 seconds.

Visual length is not entropy. A 64-character passphrase of English words can be weaker than a 32-byte random key. Prefer random bytes from a CSPRNG, then encode as hex or base64 for transport. See HS256 secret length and the HS256 glossary.

Real-World Secrets Found in Production

Security researchers using tools like jwtcrack and hashcat have found these secrets in production JWTs:

  • "secret" — the default in most tutorials
  • "your-256-bit-secret" — literally copied from documentation examples
  • "password", "admin", "test"
  • Company names, product names, developer GitHub usernames
  • "jwt_secret", "mysecretkey", "supersecretkey"

These appear because developers copy example code and forget to replace placeholder secrets before deploying. Treat any tutorial default as already public.

How to Generate a Safe Secret

Use a CSPRNG — a cryptographically secure pseudorandom number generator.

const crypto = require('crypto');
const secret = crypto.randomBytes(32).toString('hex'); // 256 bits
console.log(secret);
import secrets
print(secrets.token_hex(32))
package main

import (
    "crypto/rand"
    "encoding/hex"
    "fmt"
)

func main() {
    b := make([]byte, 32)
    if _, err := rand.Read(b); err != nil {
        panic(err)
    }
    fmt.Println(hex.EncodeToString(b))
}

In the browser, the JWT Secret Generator uses crypto.getRandomValues(), the platform CSPRNG.

Critical properties of a CSPRNG-generated secret:

  • Statistically uniform distribution — no patterns
  • Unpredictable — knowledge of previous outputs does not help predict future outputs
  • No relationship to time, process ID, or any observable state

Defence Checklist

  • [ ] Use a minimum 256-bit CSPRNG secret for HS256
  • [ ] Never use human-readable strings as secrets
  • [ ] Never reuse secrets from tutorials, examples, or documentation
  • [ ] Use different secrets for dev, staging, and production
  • [ ] Store in environment variables or a secrets manager — never in source code
  • ] Rotate annually or after any suspected exposure ([rotation guide)
  • [ ] Pin algorithms on verify (HS256 allowlist)

Frequently Asked Questions

Can rate limiting stop JWT secret brute force?

Not for offline attacks. Rate limiting protects online login endpoints. Once an attacker has a valid JWT, HMAC trials happen locally against the signature with no requests to your servers.

Is a long passphrase safer than a short random hex string?

Not necessarily. Passphrases can look long while packing little entropy. A 32-byte CSPRNG value (64 hex characters) is the practical HS256 baseline regardless of how "readable" a passphrase feels.

Does RS256 eliminate brute-force risk on the signing key?

Asymmetric signing moves the threat model: verifiers hold a public key and cannot forge with it. Private keys still must be strong and protected. For trade-offs, read HS256 vs RS256.

What should I do if I used a tutorial secret in production?

Generate a new CSPRNG secret immediately, deploy a grace-period rotation, invalidate refresh sessions if compromise is likely, and scrub git history if the old secret was ever committed.

Written by

JWTSecrets Team

Editorial Team

The JWTSecrets editorial team writes practical guides on JWT authentication, cryptographic key management, and browser-based security tooling. Our content is reviewed against IETF RFCs and current library documentation.