Security Engineering

🔑 API Key Security in 2026: Generation, Storage, Rotation, and Revocation

API Key Security in 2026: Generation, Storage, Rotation, and Revocation: API key security; CSPRNG; key rotation — key points at a glance
API Key Security in 2026: Generation, Storage, Rotation, and Revocation: API key security; CSPRNG; key rotation — key points at a glance
By Owen Blackwood · 16 October 2026 · 9 min read · 1,658 words

GitHub's 2024 secret scanning report identified over 1.1 million exposed API keys in public repositories, and that number only covers what GitHub scanned. API key security in 2026 is a four-part problem: generating keys with sufficient entropy, storing them on the server without creating a second breach risk, rotating them before compromise becomes catastrophe, and revoking them fast enough to limit damage when something does go wrong.

What is an API key? An API key is a long, high-entropy random string used to authenticate machine-to-machine requests. It identifies the calling application and authorizes access to an API's resources without requiring an interactive login. Unlike a session token, which expires in minutes or hours, an API key typically persists for weeks or months and carries persistent permissions that make its security properties similar to a privileged service account credential.

Generating a cryptographically secure API key

The most common API key mistake is generation: using a timestamp-seeded PRNG, a sequential counter, a UUID v4 with inadequate entropy, or in the worst cases, a deterministic function of the user ID. None of these meet the minimum bar.

The OWASP API Security Project recommends at least 128 bits of entropy for API keys. In practice, 192-256 bits provides comfortable margin and is trivial to implement. All three major language ecosystems provide the right primitive: crypto.randomBytes in Node.js, secrets.token_bytes in Python, and crypto/rand in Go. Do not reach for anything else.

Node.js:

const crypto = require('crypto');

function generateApiKey(prefix = 'rpk') {
  // 32 bytes = 256 bits of entropy
  const raw = crypto.randomBytes(32).toString('hex');
  return `${prefix}_${raw}`;
}
// Example output: rpk_4a7f2b91e83c6d0a58f1e27c43b96d12...

Python:

import secrets

def generate_api_key(prefix: str = "rpk") -> str:
    # secrets.token_hex uses os.urandom internally
    raw = secrets.token_hex(32)  # 64 hex chars = 256 bits
    return f"{prefix}_{raw}"

Go:

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

func GenerateAPIKey(prefix string) (string, error) {
    buf := make([]byte, 32)
    if _, err := rand.Read(buf); err != nil {
        return "", err
    }
    return fmt.Sprintf("%s_%s", prefix, hex.EncodeToString(buf)), nil
}

The prefix pattern (rpk_, sk_live_, ghp_) matters for operational reasons: it lets GitHub, GitLab, and other secret-scanning tools detect keys in source code via regex. Stripe, GitHub, and Twilio all use prefixed formats for exactly this reason. Add a prefix to every key you issue.

How to store API keys on the server

Do not store API keys in plain text. Do not store them in reversible encrypted form. Store a one-way hash.

The standard approach is a SHA-256 hash of the full key, stored in the database alongside the key's metadata (owner, permissions, created date, last-used date). When an inbound request presents a key, hash it and compare against the stored hash. The actual key value is never written to disk after the initial creation event.

import hashlib

def hash_api_key(key: str) -> str:
    return hashlib.sha256(key.encode('utf-8')).hexdigest()

# At creation: store hash_api_key(key), show key to user once, discard plaintext
# At verification: compare hash_api_key(request_key) == stored_hash

SHA-256 is appropriate here because API key lookup must be fast (one hash per request, potentially thousands per second), and the keys themselves carry sufficient entropy that a fast hash does not create a cracking risk. This is different from password storage, where the attacker can precompute a dictionary. A correctly generated 256-bit API key cannot be precomputed or dictionary-attacked regardless of hashing speed.

Show the key exactly once. Display the full key to the user at creation, then permanently discard the plaintext. Store only the hash. If the user loses the key, they revoke it and generate a new one. This is non-negotiable: if you can retrieve the plaintext later, so can anyone who breaches your database.

For lookup performance on large key tables, store the first 8 characters of the key (or a short lookup prefix) in a separate indexed column. This lets the database narrow candidates before running the hash comparison, without revealing enough of the key to be useful to an attacker with read access to the database.

Key rotation: scheduled and event-triggered

API key rotation is the practice of replacing a live key with a new one before it has been confirmed compromised. Two categories of rotation matter:

Scheduled rotation

Keys should expire on a fixed schedule. The appropriate interval depends on the permission scope and blast radius:

Key type Recommended rotation interval Reason
Read-only, low-sensitivity data 180 days Low blast radius; rotation overhead outweighs risk
Read-write, internal services 90 days Balances operational stability with dwell-time reduction
Admin or full-access keys 30 days Broad permissions justify shorter window
Payment or financial API keys 30 days or per-transaction tokens Direct financial exposure; comply with PCI DSS 8.3.9
CI/CD pipeline secrets 30 days or per-pipeline injection Pipeline configs are frequently committed to version control

Event-triggered rotation

Rotate immediately on any of these events, regardless of the scheduled interval:

"Secrets should be rotated regularly as a standard operational practice, not just in response to detected incidents. Regular rotation limits the window of opportunity for an attacker who has obtained a secret without triggering any alert." CISA Secure by Design Alert, Guidance on Software Security Best Practices, 2024

Zero-downtime rotation pattern

The naive rotation approach breaks integrations: revoke the old key, issue a new one, update every consumer simultaneously. This is operationally untenable for keys used across many services. The correct pattern is overlap rotation:

  1. Issue a new key. Both old and new keys are valid.
  2. Distribute the new key to all consumers and confirm adoption (monitor old-key usage, which should drop to zero).
  3. Revoke the old key once no requests have used it for a defined quiet period (typically 48 hours).

Secrets managers like HashiCorp Vault and AWS Secrets Manager automate this pattern. Vault's dynamic secrets engine can generate a new API credential on demand, lease it for a configured TTL, and revoke it automatically at expiry without human intervention. If you issue more than a handful of API keys, a secrets manager eliminates the operational burden of manual rotation entirely.

Revocation: speed is the only metric that matters

Revocation without speed is theater. A key revocation system that takes 10 minutes to propagate across services gives an attacker a 10-minute window after discovery. The goal is sub-second revocation across all services.

Two patterns achieve this:

Centralized validation with short-circuit check

Every inbound API request performs a hash lookup against a centralized key store. Revocation is a single database write (set revoked_at = NOW()). All subsequent requests against that hash return invalid immediately. This is the simplest model and works well when the key validation service can handle the lookup latency (sub-millisecond with a cached, indexed lookup).

Token revocation list with push invalidation

For distributed systems where each service validates keys locally, maintain a revocation list (a Redis set of revoked key hashes) that services poll every 30-60 seconds. Revoke at the source, wait for one poll cycle, and the key is dead everywhere. This trades 30-60 seconds of continued validity for lower lookup latency in the hot path.

Audit logging is a prerequisite for effective revocation. Every key usage event should be written to an immutable log: key hash prefix, timestamp, source IP, request path, response code. When investigating a suspected compromise, this log tells you exactly what the attacker accessed and for how long.

Six mistakes that make API keys a liability

Most API key incidents trace back to a short list of implementation errors:

Where password managers fit in

Developers and small teams frequently store API keys in password managers for ad-hoc access. A dedicated credential vault like NordPass Business stores API keys, SSH keys, and service credentials in an encrypted vault with role-based sharing. Team members access only the keys their role requires, and the vault maintains an audit log of every access. This is not a substitute for a programmatic secrets manager in production infrastructure, but it closes the gap for developer workstations, staging credentials, and manually managed integrations that are not yet automated.

The zero-knowledge architecture of a good password manager means that the vendor cannot read stored keys even if their servers are breached. That property is worth verifying before choosing a vault for sensitive API credentials.

Frequently asked questions

What is an API key?

An API key is a long random string used to authenticate machine-to-machine requests to an API. It identifies the calling application and authorizes access to specific resources without requiring an interactive login flow. API keys carry persistent permissions and behave like service account passwords: they must be generated securely, stored as hashes, rotated on a schedule, and revoked immediately on compromise.

How long should an API key be?

OWASP recommends at least 128 bits of entropy as a minimum. In practice, 32 bytes (256 bits) encoded as 64 hex characters or 43 base64url characters is the standard. The key must be generated by a CSPRNG. A UUID v4 provides only 122 bits and is not suitable for high-value API keys because it has a recognizable format that scanners can detect and attackers can potentially predict if generated by a weak PRNG.

Should API keys be stored in plain text?

No. Store only a SHA-256 hash of the key. Show the full key to the user once at creation, then discard the plaintext permanently. This prevents a database breach from exposing live credentials. The cost is that lost keys cannot be recovered and must be regenerated, which is the correct behavior: recovery implies the key is stored in a recoverable form, which means it can be stolen.

How often should API keys be rotated?

Every 90 days for read-write keys, every 30 days for admin or payment keys. Rotate immediately on any suspected compromise, any personnel change that affected access to the key, or any detection of anomalous usage. Use overlap rotation (new key valid before old key is revoked) to avoid downtime during scheduled rotations. Secrets managers like HashiCorp Vault can automate this process end to end.

Generate a Cryptographically Secure Key →
We use cookies to improve your experience. Learn more