This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
securitycritical PriorityID: jwt-es256-asymmetric-verification-revocation-standard

Strict ES256 Asymmetric Key Verification, JWKS Cache Invalidation, and Distributed Token Revocation

Enforces immutable cryptographic pinning to ECDSA P-256 (ES256) signature validation with robust JWKS key caching and rate-limiting. Mandates explicit verification of standard claims (iss, aud, exp, nbf) and enforces an atomic distributed blacklist lookup using a unique jti against a shared key-value store to support instantaneous token revocation.

Prohibited Anti-Pattern: Algorithm Confusion, Uncached JWKS Lookups, and Stateless Zombie Tokens

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Strict ES256 Asymmetric Key Verification, JWKS Cache Invalidation, and Distributed Token Revocation - Enforces immutable cryptographic pinning to ECDSA P-256 (ES256) signature validation with robust JWKS key caching and rate-limiting. Mandates explicit verification of standard claims (iss, aud, exp, nbf) and enforces an atomic distributed blacklist lookup using a unique jti against a shared key-value store to support instantaneous token revocation.
globs: src/auth/**/*.{ts,tsx}, src/middleware/**/*.{ts,tsx}, src/security/**/*.{ts,tsx}, src/lib/jwt/**/*.{ts,tsx}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/jwt-es256-asymmetric-verification-revocation-standard"
---

# Strict ES256 Asymmetric Key Verification, JWKS Cache Invalidation, and Distributed Token Revocation

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Algorithm Confusion, Uncached JWKS Lookups, and Stateless Zombie Tokens

## System Constraints
You are a Principal Security Architect enforcing zero-trust token verification standards. Mandate asymmetric ES256 signature verification using strict key pinning, bounded JWKS caching, and atomic jti-based distributed revocation checks. Reject any implementation that trusts the token header alg dynamically, allows HMAC-as-public-key confusion, queries remote JWKS endpoints without rate limiting, or omits distributed blacklist validation.

## Strict Guidelines
- Engineers MUST ALWAYS enforce algorithms: ['ES256'] explicitly during verification to prevent algorithm confusion attacks (e.g., alg: 'HS256' using public keys or alg: 'none').
- Engineers MUST NOT allow arbitrary JWKS retrieval URLs from the token header (such as 'jku' or 'x5u'); JWKS sources must be statically configured trusted endpoints.
- Services MUST cache remote JWKS public keys in-memory with strict TTLs and enforce request rate limiting (cooldown) to protect against denial-of-service amplification attacks.
- Engineers MUST ALWAYS validate mandatory claims: exp (expiration), nbf (not before), iss (issuer), aud (audience), and a unique jti (JWT ID) with a maximum allowable clock skew of 60 seconds.
- Components NEVER treat JWT verification as purely stateless; services MUST query an in-memory distributed store (e.g., Redis) to verify that the jti has not been revoked prior to expiration.
- Revocation entries stored in the distributed cache MUST be set with a TTL exactly equal to the token's remaining lifetime (token.exp - current_timestamp) to avoid unbounded cache bloat.

## Bad vs Good Implementations
### ES256 Verification with Cached Remote JWKS and Redis Revocation Check

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The bad example dynamically accepts the algorithm specified by the client header (vulnerable to algorithm confusion), fetches untrusted JWKS endpoints from 'jku' (SSRF), fails to cache public keys (DoS vector), and treats verification as purely stateless without checking if the token was revoked.
```typescript
import jwt from 'jsonwebtoken';

// ANTI-PATTERN: Dynamic algorithm parsing, no JWKS caching, no audience/issuer pinning, no revocation check
export async function verifyAuthToken(token: string) {
  const decodedHeader = jwt.decode(token, { complete: true })?.header;
  
  // CRITICAL VULNERABILITY: Blindly fetching jku from client-controlled header (SSRF)
  const jwksUri = decodedHeader?.jku || 'https://auth.example.com/.well-known/jwks.json';
  const res = await fetch(jwksUri); // No cache, prone to DoS
  const { keys } = await res.json();
  const key = keys.find((k: any) => k.kid === decodedHeader?.kid);

  // CRITICAL VULNERABILITY: alg parameter accepted from token header (algorithm confusion)
  return jwt.verify(token, key.x5c[0], {
    algorithms: [decodedHeader?.alg as any], // Permits HS256 / none attacks
  });
}
```

#### Production Standard (Correct)
> **Standard**: The good example pins the algorithm explicitly to 'ES256', uses a statically configured remote JWKS with strict caching and request throttling, verifies standard claims (iss, aud, exp), and executes an atomic distributed check against Redis for token revocation via jti.
```typescript
import { createRemoteJWKSet, jwtVerify } from 'jose';
import type { Redis } from 'ioredis';

const TRUSTED_ISSUER = 'https://auth.example.com';
const EXPECTED_AUDIENCE = 'https://api.example.com';
const JWKS_ENDPOINT = new URL(`${TRUSTED_ISSUER}/.well-known/jwks.json`);

// Production Invariant: Pre-configured, rate-limited, and cached JWKS client
const jwksClient = createRemoteJWKSet(JWKS_ENDPOINT, {
  cooldownDuration: 30_000, // 30s rate-limit against key-cycling DoS
  cacheMaxAge: 600_000,     // 10m cache
});

export interface TokenVerificationContext {
  redis: Redis;
  clockToleranceSeconds?: number;
}

export async function verifyAuthToken(
  token: string,
  context: TokenVerificationContext
) {
  // 1. Asymmetric verification strictly pinned to ES256 (ECDSA P-256)
  const { payload } = await jwtVerify(token, jwksClient, {
    algorithms: ['ES256'],
    issuer: TRUSTED_ISSUER,
    audience: EXPECTED_AUDIENCE,
    clockTolerance: context.clockToleranceSeconds ?? 60,
  });

  // 2. Mandatory jti presence check
  const jti = payload.jti;
  if (!jti) {
    throw new Error('Token verification failed: missing required jti claim');
  }

  // 3. Distributed token revocation check via Redis
  const isRevoked = await context.redis.exists(`token:blacklist:${jti}`);
  if (isRevoked === 1) {
    throw new Error('Token verification failed: token has been revoked');
  }

  return payload;
}
```

Recommended MCP Servers (mcp-serverlist.com)

Equip agent with system tools to verify code for this stack.

Recommended Agent Skills (askills.dev)

Ready-to-use executable skill functions tailored to this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Strict ES256 Asymmetric Key Verification, JWKS Cache Invalidation, and Distributed Token Revocation

Strict ES256 Asymmetric Key Verification, JWKS Cache Invalidation, and Distributed Token Revocation defines an industrial-grade behavioral standard for security engineering. Enforces immutable cryptographic pinning to ECDSA P-256 (ES256) signature validation with robust JWKS key caching and rate-limiting. Mandates explicit verification of standard claims (iss, aud, exp, nbf) and enforces an atomic distributed blacklist lookup using a unique jti against a shared key-value store to support instantaneous token revocation. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Algorithm Confusion, Uncached JWKS Lookups, and Stateless Zombie Tokens Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftAlgorithm Confusion, Uncached JWKS Lookups, and Stateless Zombie TokensCritical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST ALWAYS enforce algorithms

Engineers MUST ALWAYS enforce algorithms: ['ES256'] explicitly during verification to prevent algorithm confusion attacks (e.g., alg: 'HS256' using public keys or alg: 'none').

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST NOT allow arbitrary JWKS retrieval URLs from the token header (such as 'jku' or 'x5u')

Engineers MUST NOT allow arbitrary JWKS retrieval URLs from the token header (such as 'jku' or 'x5u'); JWKS sources must be statically configured trusted endpoints.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Services MUST cache remote JWKS public keys in-memory with strict TTLs and enforce request rate limiting (cooldown) to protect against denial-of-service amplification attacks.

Services MUST cache remote JWKS public keys in-memory with strict TTLs and enforce request rate limiting (cooldown) to protect against denial-of-service amplification attacks.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Engineers MUST ALWAYS validate mandatory claims

Engineers MUST ALWAYS validate mandatory claims: exp (expiration), nbf (not before), iss (issuer), aud (audience), and a unique jti (JWT ID) with a maximum allowable clock skew of 60 seconds.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Components NEVER treat JWT verification as purely stateless

Components NEVER treat JWT verification as purely stateless; services MUST query an in-memory distributed store (e.g., Redis) to verify that the jti has not been revoked prior to expiration.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
6

Revocation entries stored in the distributed cache MUST be set with a TTL exactly equal to the token's remaining lifetime (token.exp - current_timestamp) to avoid unbounded cache bloat.

Revocation entries stored in the distributed cache MUST be set with a TTL exactly equal to the token's remaining lifetime (token.exp - current_timestamp) to avoid unbounded cache bloat.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is Strict ES256 Asymmetric Key Verification, JWKS Cache Invalidation, and Distributed Token Revocation critical for AI coding assistants?

Enforces immutable cryptographic pinning to ECDSA P-256 (ES256) signature validation with robust JWKS key caching and rate-limiting. Mandates explicit verification of standard claims (iss, aud, exp, nbf) and enforces an atomic distributed blacklist lookup using a unique jti against a shared key-value store to support instantaneous token revocation. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Algorithm Confusion, Uncached JWKS Lookups, and Stateless Zombie Tokens) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

1 Rule in Stack

Strict