Docs/Continuous authorization
Continuous Authorization

Not just at login. Every request.

A validated JWT only proves a token was legitimate at issuance. Continuous authorization re-checks the agent's current state on every single proxied request, so a revocation, an admin kill switch, or a stale session takes effect immediately — not whenever the token happens to expire. This is what turns ModGate from an auth layer into a security layer.

Point-in-time vs. continuous
Point-in-time auth (industry default)
A token is checked once, at issuance. Revoke the agent and the token keeps working until it naturally expires.
Continuous authorization (ModGate)
Every proxied request re-checks the agent's live status. Revoke the agent and its very next call — even one millisecond later — is rejected.

1. Live agent-state checks (automatic)

This runs on every request through the MCP proxy — nothing to configure. Before a tool call is forwarded to your server, ModGate checks:

CheckRejected if
Agent existsThe agent identity referenced by the token has been deleted
Agent is activeThe agent has been revoked
Agent unexpiredThe agent identity's own expiresAt has passed
Not force-reauthedAn admin triggered the kill switch after this token was issued
Within reverify windowThe session has outlived its configured reverification interval

These same checks also apply to /oauth/introspect and /oauth/delegate, so third-party resource servers and orchestrator agents get identical, live-checked behavior — not a weaker version of it.

2. What a failed check looks like

HTTP 401 or 403

{
  "error": "reauthorization_required",
  "error_description": "Session exceeded the 900s continuous-authorization window. Obtain a new token.",
  "reason": "reverification_interval_exceeded"
}
reasonStatusFix
agent_not_found403Agent identity was deleted — this is unrecoverable
agent_revoked403Agent was revoked — create a new agent identity
agent_expired403Agent identity's expiresAt has passed — extend or recreate it
reauth_forced401Complete a new authorization_code exchange, not just a refresh
reverification_interval_exceeded401Refresh the token — a normal, expected occurrence, not an error state

Every rejection also fires a session.reauth_required webhook and an audit log entry — see Webhooks.

3. Tune the policy per agent

Defaults are a 900-second (15 minute) reverify window and a 120-calls-per-minute rate ceiling. Override either per agent:

PATCH https://api.modgate.io/agents/{tenantId}/{agentId}/continuous-auth
X-ModGate-API-Key: YOUR_API_KEY
Content-Type: application/json

{
  "reverifyIntervalSeconds": 120,
  "maxCallsPerMinute": 30
}

# Response — merges with any existing policy:
{
  "id": "agent_xyz789",
  "continuousAuth": {
    "reverifyIntervalSeconds": 120,
    "maxCallsPerMinute": 30
  },
  ...
}
Tighten reverifyIntervalSeconds below your access token's own TTL for your highest-privilege agents (admin-scoped, delegation-capable orchestrators) — it forces a fresh token more often than the token would naturally expire on its own.

4. Admin kill switch — force-reauth

For incident response: invalidate every outstanding token for an agent right now, without waiting for its next scheduled check or its token to expire.

POST https://api.modgate.io/agents/{tenantId}/{agentId}/force-reauth
X-ModGate-API-Key: YOUR_API_KEY

# Response:
{
  "agentId": "agent_xyz789",
  "tenantId": "org_...",
  "forceReauthAfter": 1752624000000,
  "message": "All outstanding tokens for this agent are now considered stale and will be rejected on next use."
}

Unlike revocation, force-reauth doesn't deactivate the agent — it just invalidates every token issued before this moment, including outstanding refresh tokens. The agent can resume working immediately once it completes a fresh authorization_code exchange. Use this when you're not sure an agent is compromised but want it to prove itself again; use revocation when you're sure.

5. See every agent's posture at a glance

GET https://api.modgate.io/sessions/{tenantId}
X-ModGate-API-Key: YOUR_API_KEY

# Response:
{
  "tenantId": "org_...",
  "sessions": [
    {
      "agentId": "agent_xyz789",
      "name": "billing-bot",
      "active": true,
      "reverifyIntervalSeconds": 900,
      "maxCallsPerMinute": 120,
      "reauthForced": false,
      "forceReauthAfter": null
    }
  ],
  "total": 1
}

Useful for a dashboard panel, or a quick sanity check before an incident call: which agents currently have a forced reauth in effect, and what policy each is running under.

6. Rate-anomaly detection

Independent of the checks above, every proxied call also counts against a rolling 60-second per-agent window. Exceed maxCallsPerMinute and the call is rejected with 429 rate_limited, and an anomaly.rate_exceeded webhook fires — a compromised or malfunctioning agent burning through calls gets caught immediately, not whenever someone happens to check the audit log.