Data and secrets

Use secure randomness

Generate session identifiers, reset tokens, nonces, and keys with a cryptographically secure system source instead of predictable application randomness.

Security tokens must be difficult to guess. That sounds trivial until you see what real code uses: timestamps, counters, Math.random(), or UUID variants built from weak randomness. All of them look random. None of them are unpredictable.

The distinction matters because an attacker does not need to guess the whole token. They need to shrink the search space. A token derived from the clock has a few thousand plausible values in the window around “now.” That is a for-loop, not a defense.

Use the platform generator

Every platform ships a cryptographically secure random source. Use it, and do not reimplement it:

// a random identifier with strong randomness built in
const token = crypto.randomUUID()

// or explicit bytes when you control the format
const bytes = crypto.getRandomValues(new Uint8Array(32))
const reset = Buffer.from(bytes).toString('base64url')

Request enough bytes — 16 is a floor, 32 is comfortable for a reset token — and encode them safely for the channel, like base64url for URLs. Then keep the raw token out of logs, because a perfectly random token in a log file is a perfectly readable one.

Math.random() exists for shuffling playlists. It is seeded from predictable state and was never designed to resist prediction.

A reset link is built from the user ID plus the current timestamp:

// looks random enough, is enumerable
const token = `${userId}-${Date.now()}`

An attacker who knows the target’s email requests a reset, notes the time, and tries nearby timestamp values until one works. Account taken over, no exotic vulnerability needed, because the token was never secret — only obscure.

Length would not have saved it. A long token is not strong when its source is predictable. And a custom “mixing” step — hashing the timestamp, appending the user ID — adds obscurity, not randomness. The unpredictability of the output can never exceed the unpredictability of the inputs.

Verify your generator

Find where your app generates reset tokens and record which API it calls and how many bytes it requests. Generate a few thousand tokens and check format and uniqueness. Then freeze time in a test and generate more: with a mocked clock, a secure generator keeps producing unpredictable values, while a timestamp-derived one collapses into repeats. That one test separates real randomness from decoration.

Lesson completed

Take this course offline

Get every free book, course edition, and software download.

Get the download library →