Skip to main content
Anubis uses cryptographic signing to secure challenge tokens and prevent tampering. This page covers key generation, JWT signing, and cookie security.

JWT Signing

Challenge solutions are stored in JWT (JSON Web Tokens) signed with either:
  • Ed25519 (recommended) - Elliptic curve signatures
  • HMAC-SHA512 - Symmetric key signing
Ed25519 provides fast, secure signatures with small key sizes.

Generate Key

Configure Anubis

HMAC-SHA512

Symmetric signing using a shared secret.
Note: Ed25519 is preferred. HMAC-SHA512 is legacy.

Random Key (Development Only)

If no key is configured, Anubis generates a random key on startup:
Consequences:
  • Challenges invalidated on restart
  • Multi-instance deployments won’t work
  • Users must re-solve challenges after deployment
⚠️ Never use random keys in production

Key Management

Storage Requirements

Keys must be:
  1. Persistent - Survives container/pod restarts
  2. Secret - Not committed to version control
  3. Accessible - Readable by Anubis process

File Permissions

Docker/Kubernetes

Docker Secret

Kubernetes Secret

Key Rotation

  1. Generate new key
  2. Deploy Anubis with new key
  3. Existing JWTs remain valid until expiry
  4. New challenges use new key
No downtime required. Users with old cookies will re-solve challenges. Anubis sets multiple security flags on cookies.

Secure Flag

Requires HTTPS:
If --cookie-secure=false, SameSite automatically downgrades from None to Lax.

SameSite

Controls cross-site cookie sending:
Default: None (with Secure flag)

Partitioned (CHIPS)

Enable Cookies Having Independent Partitioned State:
Required for third-party cookies in Chrome (2024+). Share cookies across subdomains:
Static domain:
  • Cookie valid for *.example.com
  • Set once, works everywhere
Dynamic domain:
  • Cookie valid for request domain only
  • Users on www.example.com and api.example.com get separate cookies
⚠️ Cannot use both: Setting both flags is an error.
After expiration, users must re-solve challenges. Customize cookie names:
Use different prefixes when running multiple Anubis instances on the same domain.

JWT Claims

JWT payload contains:

Difficulty in JWT

Include challenge difficulty in token:
Use cases:
  • Track which difficulty was solved
  • Audit challenge settings
  • Debug multi-difficulty policies

JWT IP Restriction

Bind JWT to specific IP address:
If set, JWT is only valid when request comes from the same IP that solved the challenge. Limitations:
  • Breaks mobile users (IP changes)
  • Issues with carrier-grade NAT
  • Only use if your threat model requires it

Security Best Practices

Key Generation

Do:
  • Use cryptographically secure random number generator
  • Store keys in secrets management (Vault, AWS Secrets Manager)
  • Rotate keys periodically
  • Use Ed25519 (not HMAC-SHA512)
🚫 Don’t:
  • Commit keys to version control
  • Use the same key across environments
  • Share keys between services
  • Use predictable/weak keys
Do:
  • Use --cookie-secure in production (HTTPS only)
  • Set appropriate --cookie-same-site for your use case
  • Use short expiration times (balance security vs UX)
  • Enable --cookie-partitioned for third-party contexts
🚫 Don’t:
  • Disable --cookie-secure in production
  • Use SameSite=None without HTTPS
  • Set extremely long expiration times
  • Ignore browser warnings about cookie flags

Deployment

Do:
  • Always configure signing keys in production
  • Use persistent storage backends (bbolt, valkey, s3api)
  • Monitor for “generating random key” warnings
  • Test key rotation procedure
🚫 Don’t:
  • Rely on random key generation
  • Use memory storage backend in production
  • Forget to mount secrets in containers
  • Share signing keys across environments

Validation Errors

Key Validation

Conflicting Configuration

Persistent Storage Warning

When using persistent storage without a configured key:
Impact:
  • All active users must re-solve challenges after restart
  • Degraded user experience
  • Potential spike in challenge traffic
Fix: Configure a signing key (see Key Generation).

Next Steps