This post begins a short series about authentication mistakes I often see in Node.js/Express applications. We’ll look at a real-but-safe example where the server uses JSON Web Tokens (JWTs) for authentication, but the signing secret is weak and guessable. That weakness lets an attacker forge tokens that the server accepts.
The goal here is educational: to show how this class of bug appears in an Express app, I will not publish exploit scripts or wordlists; instead, this walkthrough focuses on how to find the problem.
Summary of the vulnerable setup:
- A Node.js server built with Express issues JWTs using the HS256 algorithm.
- The server stores the signing key as a short or common string (for example, “secret”, “1234”, or an English word).
- Because the secret is weak, an attacker who can guess it can sign arbitrary tokens (for example, upgrading their user to admin) and the server will accept them.
What you’ll learn in this post:
- How to spot weak JWT secrets in code and runtime configuration.
If you want to follow along locally, create a tiny Express app and never expose test secrets to the public internet. Treat any reproduction data as lab-only, and rotate secrets after testing.
Endpoints
- /login
- /admin
Walkthrough
We have these credentials:
const users = [
{ id: 1, username: 'alice', password: 'alicepw', role: 'user' },
{ id: 2, username: 'bob', password: 'bobpw', role: 'admin' }
];

If we try to access /admin, we get something like:

If we use this site: SuperTokens JWT Decoder, we can decode the JWT.

If we change the role from user to admin to see if we can access the /login endpoint, we get this:


Brute-Force

Let’s use hashcat to brute-force the JWT

secret

Welcome, admin Alice
