---
title: "Make tokens from a secure random source · Agent Wranglers"
url: https://agentwranglers.se/playbook/application-security/authentication-and-sessions/secure-random-tokens
id: APS-14
level: Recommended
applies: accounts
updated: 2026-10-27
build: a2a6bdfed830
tokens: 1035
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Make tokens from a secure random source

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Authentication and sessions](https://agentwranglers.se/playbook/application-security/authentication-and-sessions.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-27.

- ID: APS-14
- Level: Recommended
- Chapter: [Authentication and sessions](https://agentwranglers.se/playbook/application-security/authentication-and-sessions.md)
- Rule: Make session IDs, reset codes, API keys and invite links only with the platform's cryptographic random generator. Never use the plain random function, a timestamp or a counter.
- Check: Search the code for `Math.random`, `random.random`, `random.choice`, `mt_rand`, `uniqid` and `math/rand`. No match makes a token, code or ID that grants access.
- Applies when: The project has user accounts.
- How: Use `crypto.randomBytes` or `crypto.randomUUID` in Node, the `secrets` module in Python, `random_bytes` in PHP, `SecureRandom` in Java and Ruby, and `crypto/rand` in Go. Plain generators such as `Math.random` are fast but predictable, so an attacker who sees a few values can work out the next. API keys also follow [Store API keys as hashes](https://agentwranglers.se/playbook/api-design/api-security/api-keys.md). Make each token as long as [Lock down session cookies](https://agentwranglers.se/playbook/application-security/authentication-and-sessions/session-cookies.md) says. Links in email also follow [single-use and short-lived links](https://agentwranglers.se/playbook/accounts/sign-in-methods/sign-in-links.md).

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### JavaScript example

```js
import { randomBytes } from 'node:crypto';

// Bad: predictable
const resetCode = Math.random().toString(36).slice(2);
// Good
const resetToken = randomBytes(32).toString('base64url');
```

### Python example

```python
import secrets

# Bad: predictable
reset_code = str(random.randint(100000, 999999))
# Good
reset_token = secrets.token_urlsafe(32)
```

## Sources

- [OWASP Cryptographic Storage Cheat Sheet on secure random numbers](https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#secure-random-number-generation)

## Related rules

- ECM-11 [Let guests check out without an account](https://agentwranglers.se/playbook/ecommerce/carts-and-checkout/guest-checkout.md) in E-commerce and fulfilment
- API-42 [Store API keys as hashes](https://agentwranglers.se/playbook/api-design/api-security/api-keys.md) in API design
- APS-16 [Lock down session cookies](https://agentwranglers.se/playbook/application-security/authentication-and-sessions/session-cookies.md) in Application security
- ACC-69 [Make sign-in and reset links single-use and short-lived](https://agentwranglers.se/playbook/accounts/sign-in-methods/sign-in-links.md) in Accounts and identity
- APS-56 [Use only standard cryptography](https://agentwranglers.se/playbook/application-security/cryptography-and-keys/standard-cryptography.md) in Application security

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/application-security/authentication-and-sessions/secure-random-tokens">Agent Wranglers application security playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Compare secrets in constant time](https://agentwranglers.se/playbook/application-security/authentication-and-sessions/constant-time-compare.md)
- Next: [Trust an email domain only after strict parsing](https://agentwranglers.se/playbook/application-security/authentication-and-sessions/strict-email-parsing.md)
- [Authentication and sessions](https://agentwranglers.se/playbook/application-security/authentication-and-sessions.md)
