Get a Pentest and security assessment of your IT network.

Cyber Security

Secure Single-Use Token Generation

TL;DR

The method you’re likely using (generating tokens with predictable sequences or weak randomness) is probably insecure. This guide shows how to create genuinely single-use tokens that are much harder to guess and prevent reuse.

Understanding the Risks

If your tokens aren’t strong enough, attackers can:

  • Guess them: If they know (or can figure out) how you generate tokens, they can create valid ones.
  • Reuse them: If a token isn’t properly invalidated after use, it can be used multiple times.

This leads to serious cyber security problems like unauthorised access and data breaches.

How to Generate Secure Single-Use Tokens

  1. Choose a Cryptographically Secure Random Number Generator (CSPRNG): Don’t use standard rand() functions. These aren’t designed for security.
    • Python: Use the secrets module.
    • PHP: Use random_bytes() or openssl_random_pseudo_bytes().
    • JavaScript (Node.js): Use the crypto module.
  2. Generate a Sufficiently Long Token: Longer tokens are harder to guess.
    • Aim for at least 32 bytes (256 bits) of random data. This translates to roughly 58 hexadecimal characters.
  3. Encode the Token: Use a safe encoding like Base64 or hexadecimal.
    • Base64 is more compact, but hexadecimal can be easier to debug.
    • Python example (Base64):
      import secrets
      import base64
      token_bytes = secrets.token_bytes(32)
      token_string = base64.b64encode(token_bytes).decode('utf-8')
      print(token_string)
  4. Store Tokens Securely:
    • Database: Use a properly configured database with appropriate access controls. Hash the token before storing it (see step 6).
    • Avoid storing tokens in plain text!
  5. Implement Token Validation and Invalidation: This is crucial.
    • When a token is used, immediately mark it as invalid. A simple way is to add a ‘used’ flag to the database record.
    • Consider using a short Time-To-Live (TTL) for tokens even if they haven’t been used – this adds an extra layer of security.
  6. Hash Tokens Before Storing: Even with other precautions, hashing provides an additional level of protection.
    • Use a strong hashing algorithm like SHA-256 or Argon2.
      import hashlib
      hash_object = hashlib.sha256(token_string.encode('utf-8'))
      hashed_token = hash_object.hexdigest()
      print(hashed_token)
  7. Prevent Token Reuse:
    • Before accepting a token, check if it exists in the database and is marked as unused.
    • If used, reject the request immediately.

Example Workflow

  1. User requests access.
  2. Generate a new secure token (steps 1-3).
  3. Hash the token (step 6).
  4. Store the hashed token in the database with a ‘used’ flag set to false.
  5. Send the token to the user.
  6. When the user submits the token:
    • Check if the submitted token’s hash exists in the database.
    • If it exists, check if the ‘used’ flag is false.
    • If both conditions are true:
      • Mark the ‘used’ flag as true.
      • Grant access.
    • Otherwise, reject the request.
Related posts
Cyber Security

Zip Codes & PII: Are They Personal Data?

Cyber Security

Zero-Day Vulnerabilities: User Defence Guide

Cyber Security

Zero Knowledge Voting with Trusted Server

Cyber Security

ZeroNet: 51% Attack Risks & Mitigation