This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
securitycritical PriorityID: openid-caep-realtime-token-revocation-guardrail

OpenID CAEP Real-Time Token Revocation and SET Invalidation Standard

Enforces strict cryptographic verification, tenant-isolated routing, and deterministic replay mitigation for OpenID Continuous Access Evaluation Profile (CAEP) Security Event Tokens (SETs). Guarantees that token revocations and device posture updates are validated against verified issuer JWKS and propagated to distributed token caches within sub-second latencies.

Prohibited Anti-Pattern: Unvalidated SET Payloads, In-Memory Non-Distributed Revocations, and Missing JTI Replay Defense

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: OpenID CAEP Real-Time Token Revocation and SET Invalidation Standard - Enforces strict cryptographic verification, tenant-isolated routing, and deterministic replay mitigation for OpenID Continuous Access Evaluation Profile (CAEP) Security Event Tokens (SETs). Guarantees that token revocations and device posture updates are validated against verified issuer JWKS and propagated to distributed token caches within sub-second latencies.
globs: src/auth/**/*.{ts,tsx,js}, src/security/**/*.{ts,tsx,js}, src/middleware/**/*.{ts,tsx,js}, src/events/**/*.{ts,tsx,js}, src/services/caep/**/*.{ts,tsx,js}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/openid-caep-realtime-token-revocation-guardrail"
---

# OpenID CAEP Real-Time Token Revocation and SET Invalidation Standard

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Unvalidated SET Payloads, In-Memory Non-Distributed Revocations, and Missing JTI Replay Defense

## System Constraints
You are a Principal Security Architect enforcing OpenID Shared Signals and Events (SSE) and Continuous Access Evaluation Profile (CAEP) standards across all service boundaries. You must reject any insecure SET parsing, unverified transmitters, lack of JTI deduplication, or non-distributed session revocation state.

## Strict Guidelines
- Engineers MUST ALWAYS cryptographically verify the signature of every Security Event Token (SET, RFC 8417) against the tenant-specific Identity Provider JWKS using verified cryptographic libraries (e.g., 'jose').
- Engineers MUST ALWAYS enforce strict validation of standard claims: 'iss' (issuer matches configured tenant IdP), 'aud' (audience matches client identifier), 'iat' (issued within clock skew tolerance <= 60 seconds), and a unique 'jti' identifier.
- Engineers MUST NOT decode SET payloads via naive base64 or unverified JWT parsing ('jwt.decode()') prior to complete cryptographic verification.
- Services MUST atomically persist and verify the 'jti' in a distributed store (e.g., Redis) using an idempotency key with TTL matching event validity to prevent replay attacks.
- Services MUST broadcast session invalidation and token revocation across a distributed cache or pub/sub bus to ensure sub-second global invalidation across all edge gateways and stateless APIs.
- Components NEVER store revocation state exclusively in local process memory, as this leads to split-brain access across distributed application replicas.
- Engineers MUST validate the CAEP event URI explicitly (e.g., 'https://schemas.openid.net/secevent/caep/event-type/session-revoked') and enforce schema-specific validation on subject identifiers ('sub_id').

## Bad vs Good Implementations
### CAEP SET Webhook Invalidation Handler

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The code decodes the JWT payload without cryptographic verification against the IdP's JWKS, exposing the system to arbitrary token forgery. It fails to validate 'iss', 'aud', and 'jti', enabling replay and cross-tenant attacks, and stores revocation state in process memory instead of a distributed real-time cache.
```typescript
import express, { Request, Response } from 'express';

// ANTI-PATTERN: Local in-memory set (breaks multi-replica setups),
// naive token decoding without signature/issuer validation, and no replay check
const revokedSessions = new Set<string>();

export const caepWebhook = async (req: Request, res: Response) => {
  const rawToken = req.body;
  
  // VULNERABILITY: Decoding JWT without verifying signature or issuer
  const parts = (typeof rawToken === 'string' ? rawToken : '').split('.');
  if (parts.length !== 3) {
    return res.status(400).send('Invalid token format');
  }
  
  const payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString('utf8'));
  const events = payload.events;
  
  // VULNERABILITY: No tenant check, no audience check, no jti replay defense
  const sessionRevoked = events?.['https://schemas.openid.net/secevent/caep/event-type/session-revoked'];
  if (sessionRevoked) {
    const sessionId = sessionRevoked.sub_id?.session_id;
    if (sessionId) {
      revokedSessions.add(sessionId); // In-memory only
    }
  }

  return res.status(202).send('Accepted');
};
```

#### Production Standard (Correct)
> **Standard**: The production implementation strictly verifies the cryptographic signature of the SET using tenant-isolated JWKS, validates 'iss' and 'aud' boundaries, prevents replay attacks via atomic distributed JTI deduplication, and coordinates sub-second revocation across instances using Redis key expiration and pub/sub.
```typescript
import { Request, Response } from 'express';
import { createRemoteJWKSet, jwtVerify } from 'jose';
import { Redis } from 'ioredis';

const redis = new Redis(process.env.REDIS_REVOCATION_URL!);
const CAEP_SESSION_REVOKED_URI = 'https://schemas.openid.net/secevent/caep/event-type/session-revoked';
const CLOCK_TOLERANCE_SECONDS = 60;
const JTI_REPLAY_TTL_SECONDS = 86400; // 24 hours

interface TenantConfig {
  expectedIssuer: string;
  expectedAudience: string;
  jwksUri: string;
}

// Resolves tenant-specific IdP settings securely
declare function getTenantConfig(tenantId: string): Promise<TenantConfig>;

export const handleCaepEvent = async (req: Request, res: Response): Promise<Response> => {
  const tenantId = req.headers['x-tenant-id'] as string;
  const rawSet = req.body;

  if (!tenantId || typeof rawSet !== 'string') {
    return res.status(400).json({ error: 'invalid_request' });
  }

  try {
    const config = await getTenantConfig(tenantId);
    const jwks = createRemoteJWKSet(new URL(config.jwksUri), { cacheMaxAge: 3600000 });

    // 1. Cryptographically verify signature, audience, and issuer
    const { payload } = await jwtVerify(rawSet, jwks, {
      issuer: config.expectedIssuer,
      audience: config.expectedAudience,
      clockTolerance: CLOCK_TOLERANCE_SECONDS,
    });

    const jti = payload.jti;
    if (!jti) {
      return res.status(400).json({ error: 'missing_jti' });
    }

    // 2. Replay protection: Atomically register JTI in distributed store
    const isNewJti = await redis.set(`caep:jti:${tenantId}:${jti}`, '1', 'EX', JTI_REPLAY_TTL_SECONDS, 'NX');
    if (!isNewJti) {
      return res.status(409).json({ error: 'replay_detected' });
    }

    // 3. Process events adhering strictly to OpenID CAEP schema
    const events = payload.events as Record<string, unknown> | undefined;
    if (events && CAEP_SESSION_REVOKED_URI in events) {
      const eventPayload = events[CAEP_SESSION_REVOKED_URI] as {
        sub_id?: { format?: string; session_id?: string; user?: string };
      };

      const sessionId = eventPayload?.sub_id?.session_id;
      if (sessionId) {
        // Sub-second distributed invalidation: Set in Redis with token TTL and broadcast
        const maxSessionLifetime = 86400;
        await redis.setex(`revoked:session:${tenantId}:${sessionId}`, maxSessionLifetime, 'revoked');
        await redis.publish('revocations:channel', JSON.stringify({ tenantId, sessionId, revokedAt: Date.now() }));
      }
    }

    return res.status(202).json({ status: 'processed' });
  } catch (error) {
    return res.status(401).json({ error: 'token_verification_failed' });
  }
};
```

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: OpenID CAEP Real-Time Token Revocation and SET Invalidation Standard

OpenID CAEP Real-Time Token Revocation and SET Invalidation Standard defines an industrial-grade behavioral standard for security engineering. Enforces strict cryptographic verification, tenant-isolated routing, and deterministic replay mitigation for OpenID Continuous Access Evaluation Profile (CAEP) Security Event Tokens (SETs). Guarantees that token revocations and device posture updates are validated against verified issuer JWKS and propagated to distributed token caches within sub-second latencies. 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: Unvalidated SET Payloads, In-Memory Non-Distributed Revocations, and Missing JTI Replay Defense 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 DriftUnvalidated SET Payloads, In-Memory Non-Distributed Revocations, and Missing JTI Replay DefenseCritical
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 cryptographically verify the signature of every Security Event Token (SET, RFC 8417) against the tenant-specific Identity Provider JWKS using verified cryptographic libraries (e.g., 'jose').

Engineers MUST ALWAYS cryptographically verify the signature of every Security Event Token (SET, RFC 8417) against the tenant-specific Identity Provider JWKS using verified cryptographic libraries (e.g., 'jose').

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 ALWAYS enforce strict validation of standard claims

Engineers MUST ALWAYS enforce strict validation of standard claims: 'iss' (issuer matches configured tenant IdP), 'aud' (audience matches client identifier), 'iat' (issued within clock skew tolerance <= 60 seconds), and a unique 'jti' identifier.

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

Engineers MUST NOT decode SET payloads via naive base64 or unverified JWT parsing ('jwt.decode()') prior to complete cryptographic verification.

Engineers MUST NOT decode SET payloads via naive base64 or unverified JWT parsing ('jwt.decode()') prior to complete cryptographic verification.

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

Services MUST atomically persist and verify the 'jti' in a distributed store (e.g., Redis) using an idempotency key with TTL matching event validity to prevent replay attacks.

Services MUST atomically persist and verify the 'jti' in a distributed store (e.g., Redis) using an idempotency key with TTL matching event validity to prevent replay 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.
5

Services MUST broadcast session invalidation and token revocation across a distributed cache or pub/sub bus to ensure sub-second global invalidation across all edge gateways and stateless APIs.

Services MUST broadcast session invalidation and token revocation across a distributed cache or pub/sub bus to ensure sub-second global invalidation across all edge gateways and stateless APIs.

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

Components NEVER store revocation state exclusively in local process memory, as this leads to split-brain access across distributed application replicas.

Components NEVER store revocation state exclusively in local process memory, as this leads to split-brain access across distributed application replicas.

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.
7

Engineers MUST validate the CAEP event URI explicitly (e.g., 'https

Engineers MUST validate the CAEP event URI explicitly (e.g., 'https://schemas.openid.net/secevent/caep/event-type/session-revoked') and enforce schema-specific validation on subject identifiers ('sub_id').

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 OpenID CAEP Real-Time Token Revocation and SET Invalidation Standard critical for AI coding assistants?

Enforces strict cryptographic verification, tenant-isolated routing, and deterministic replay mitigation for OpenID Continuous Access Evaluation Profile (CAEP) Security Event Tokens (SETs). Guarantees that token revocations and device posture updates are validated against verified issuer JWKS and propagated to distributed token caches within sub-second latencies. 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 (Unvalidated SET Payloads, In-Memory Non-Distributed Revocations, and Missing JTI Replay Defense) 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

OpenID