Signals and Revocation

CAE signals for real-time token revocation — 7 signal types (session_revoked, identity_compromised, tool_abuse_detected, etc.), client.signals.ingest(), and how signals interact with tokens.session().

Tokens have a finite lifetime, but trust can be lost before a token expires. Continuous Access Evaluation (CAE) signals give you a way to communicate that something has changed — immediately — without waiting for the next token refresh cycle.

The Problem with Relying on TTL Alone

Short TTLs reduce the blast radius of a compromised credential. But they do not eliminate it. A 15-minute token can still cause damage for 15 minutes after you discover a problem. In a multi-agent system, that window multiplies across every active session.

CAE signals close that window. When you ingest a signal against an identity, ZeroID marks its sessions as inactive. Any downstream service that verifies the token via introspection will immediately see active: false instead of the cached valid state, regardless of when the token expires.

This lets you move from "wait for expiry" to "revoke now, enforce everywhere."

Signal Types

Each signal type describes a specific kind of event. Use the most specific type that matches your situation.

Signal Type
When to Use

session_revoked

You want to explicitly end an active session immediately. Use for emergency shutdowns, forced logouts, or after detecting a breach.

credential_change

A key has been rotated, a secret has been updated, or credentials associated with the identity have changed. Signals that existing tokens may no longer reflect the current credential state.

ip_change

The identity is operating from an unexpected IP address or network. Use to flag out-of-policy network behavior.

anomalous_behavior

The identity is behaving in a way that deviates from its baseline — unusual request volume, unexpected scope usage, or timing anomalies.

policy_violation

The identity attempted or performed something that violates its defined operating policy. Use after a policy enforcement event.

retirement

The identity is being decommissioned. Signals that no new sessions should be accepted and existing ones should be wound down.

owner_change

The human or system entity responsible for this identity has changed. Use when an agent changes hands or its controlling principal is updated.

Severity Levels

Every signal carries a severity that downstream consumers can use to calibrate their response.

Severity
Meaning

low

Informational. Something changed, but no immediate action is required.

medium

Warrants investigation or monitoring. Active sessions may continue under watch.

high

Warrants immediate review. Consider suspending or restricting the identity.

critical

Treat as a breach or emergency. Revoke immediately.

ZeroID does not automatically take different actions based on severity — it records the signal and marks sessions appropriately. Severity is a signal to your system and operators.

Ingesting a Signal

Python

TypeScript

What Happens After a Signal Is Ingested

When ZeroID receives a signal:

  1. The signal is recorded against the identity.

  2. Active sessions for that identity are marked inactive.

  3. Token introspection for any token belonging to that identity returns active: false.

  4. The signal is available in the identity's event history for audit purposes.

Propagation is immediate within ZeroID. There is no polling delay between signal ingestion and the change in introspection behavior. The gap is whatever latency exists between your downstream service calling introspection and ZeroID processing the signal — typically sub-second.

Tokens themselves are not modified or deleted. They are not invalidated at the JWT level. What changes is the state that introspection reflects. Downstream services that rely on local JWT signature verification only (without calling introspection) will not see the revocation. See the section on common mistakes below.

How Downstream Services Should Respond

The correct pattern for a downstream service receiving a token from an agent:

  1. Verify the JWT signature using the JWKS endpoint.

  2. Check the standard JWT claims (expiry, issuer, audience).

  3. For sensitive operations, call token introspection and check that active: true.

  4. On any 401 Unauthorized response from a resource server, re-verify via introspection before retrying.

When introspection returns active: false, the downstream service should:

  • reject the request

  • return 401 Unauthorized to the caller

  • not cache the valid result from a previous introspection call

The session.active field on a retrieved session object reflects the same state. If you are building an orchestrator that holds references to sub-agent sessions, check session.active before dispatching work to a sub-agent. Do not assume a session you opened earlier is still valid.

REST Example

Practical Patterns

Emergency Shutdown

Use when you need an identity stopped immediately — breach suspected, runaway agent, or unexpected behavior at production scale.

Deactivating the identity prevents new token issuance. The signal terminates existing sessions. Both steps are needed for a complete shutdown.

Suspicious Behavior — Monitor Mode

Use when you want to flag an identity for closer inspection without immediately terminating it. Ingest a signal at medium or high severity, but do not revoke the session. This leaves the identity running while giving your monitoring systems a signal to increase scrutiny.

Your downstream services or monitoring layer can read this signal from the event history and apply stricter rate limiting or logging without forcing a re-auth cycle.

Key Rotation Event

Use when a credential backing an identity has been rotated. Existing tokens were issued under the old key. Ingesting a credential_change signal tells downstream systems to re-verify those tokens rather than trust cached state.

After this signal, any downstream service calling introspection on a token issued before the rotation will get active: false. The agent will need to re-authenticate to receive a token issued under the new key.

Agent Retirement

Use when decommissioning an identity permanently. The retirement signal communicates intent to other services and audit consumers. Pair it with deactivate to enforce it.

Signal before deactivating so that downstream systems that consume the event history have a record of the intent, not just the state change.

Common Mistakes

Avoid:

  • Relying only on token expiry for revocation. A 15-minute TTL is not a revocation mechanism. If you discover a problem at minute zero, you still have a 15-minute exposure window. Ingest a signal immediately.

  • Verifying tokens only via local JWT signature checks. Local verification confirms the signature is valid. It does not check whether the session is still active. For any sensitive operation, call introspection.

  • Caching introspection results for too long. If you cache a active: true result for several minutes, you have recreated the TTL problem at a different layer. Keep introspection cache TTLs short, or skip caching entirely for high-value operations.

  • Not checking session.active before dispatching to sub-agents. In orchestrator patterns, sessions you opened for sub-agents can be revoked while your orchestrator is still running. Always check session.active before dispatching new work.

  • Ingesting signals without a meaningful source. The source field is part of the audit record. A value like "my-service" is more useful than "unknown" when you are tracing an incident after the fact.

  • Skipping the retirement signal and deactivating directly. Deactivation changes state without explanation. The retirement signal provides context to audit consumers and downstream systems that may be reading the event history.

What's Next?

Last updated