---
title: "Security operations"
description: "Threat model, deployment controls, observability, and incident response."
image: "https://adonisjs-jwt.pages.dev/og.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://adonisjs-jwt.pages.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Security operations

## Enforced invariants

- Verification pins one configured algorithm; token headers never choose the allowlist.
- `alg: none`, unknown `kid`, bad signatures, wrong issuer/audience, malformed claims, and missing
  required claims are rejected.
- Access tokens are short-lived and require `iss`, `aud`, `sub`, `jti`, `iat`, `nbf`, and `exp`.
- Refresh secrets are high entropy, SHA-256 hashed at rest, rotated on use, and retained as
  tombstones for replay detection.
- Telemetry records guard, key ID, and outcome only. Raw tokens and personally identifiable data are
  forbidden in events, logs, and spans.

## Production checklist

- Store private PEMs, HS256 secrets, database credentials, and encryption keys in a secret manager.
- Keep JWT signing keys separate from `APP_KEY` and rotate both using independent procedures.
- Use Ed25519 or another asymmetric algorithm unless all verifiers are equally trusted to mint.
- Use HTTPS, strict CORS, and `secure` cookies. Never place bearer or refresh tokens in URLs.
- Keep access TTLs in minutes. Set refresh TTLs to the session lifetime the product actually needs.
- Rate-limit login and refresh endpoints. Alert on refresh reuse and repeated authentication failure.
- Use a shared cache denylist when logout must revoke access immediately across multiple instances.
- Back up the encrypted signing-key table with the encryption key ring required to decrypt it.
- Treat any token copied into logs, tickets, analytics, or crash reports as compromised.

## Stable errors

Package exceptions render `{ errors: [{ code, message }] }`. Relevant codes include
`E_TOKEN_EXPIRED`, `E_TOKEN_REVOKED`, `E_INVALID_REFRESH_TOKEN`,
`E_REFRESH_TOKEN_REUSE`, `E_CSRF_TOKEN_MISMATCH`, and `E_JWT_CONFIG`.
Do not return parser or JOSE internals to clients.

## Events and traces

Subscribe to the typed events `jwt:login`, `jwt:authenticated`, `jwt:authentication_failed`,
`jwt:refreshed`, `jwt:refresh_reuse_detected`, `jwt:logout`, and `jwt:key_rotated`. The package
creates `jwt.issue`, `jwt.verify`, `jwt.refresh`, and `jwt.reuse_detected` OpenTelemetry spans.

## Incident response

1. **Leaked access token:** add its `jti` to a shared denylist until `exp`; investigate the source.
2. **Leaked refresh token:** revoke the token family or all refresh tokens for the user; require login.
3. **Signing key compromise:** introduce and promote a new database key, remove the compromised key
   from verification immediately if active forgery risk outweighs breaking live access tokens, then
   revoke affected refresh sessions.
4. **Refresh reuse alert:** the family is already revoked by the package. Invalidate the client
   session, notify the user when appropriate, and review IP/device evidence outside token telemetry.
5. **Database or encryption-key compromise:** assume refresh hashes and encrypted private material
   are exposed; rotate signing and encryption keys and invalidate sessions according to risk.

Report package vulnerabilities using the private process in the repository `SECURITY.md`, not a
public issue.

Source: https://adonisjs-jwt.pages.dev/security/index.mdx
