---
title: Revoke once, access stops | Keycard
description: Withdraw an agent's access in one place and the next request fails, with both the revocation and the refusal in the audit trail. What that does and does not reach, stated plainly.
---

When something goes wrong you need access to stop, and you need to be able to show that it stopped. This is what one revocation actually reaches, and where the edges are.

## The problem

Containment for agents usually means rotating credentials across every system that holds one. That is slow at the moment when speed is the whole point, and it is hard to prove afterwards.

The proof is the harder half. Rotating a secret leaves no record tying the incident to the moment access ended. When an auditor asks when this agent lost access, the answer is reconstructed from deployment timestamps rather than read from a log.

Standing access makes it worse. An agent holding a long-lived credential has access from the moment it was granted until someone remembers to take it away, so the window is measured in however long it took to notice.

## When this applies

- You need to withdraw one agent’s or one person’s access without redeploying anything
- A reviewer wants evidence that access ended, not an assurance
- Access was granted per user and per Resource, so it can be withdrawn the same way
- You are being asked what your containment story is, and you would rather answer precisely than confidently

Suppose a contractor’s engagement ends, or an agent starts making requests that look wrong. You want the next request that agent makes to fail, you want to know it failed, and you want the record to show both the withdrawal and the refusal.

### When it does not

Where the agent obtained a credential outside Keycard, revoking here reaches nothing, because the coverage is the credentials Keycard issues.

Where the downstream system holds its own long-lived credential that Keycard brokered rather than minted, withdrawal behaves differently. That case is covered below and it is the one most likely to surprise a reviewer.

## The solution

Access is granted per User and per Resource, so it can be withdrawn the same way. Revoking a grant tells Keycard to stop satisfying requests for that pairing.

The next time the Application asks for a credential, whether that is a fresh exchange or a refresh, there is no grant to satisfy it and the request fails. The User has to authorize again before anything is issued.

Both halves land in the [Audit Log](/admin/audit-log-and-sessions/index.md). The withdrawal is an event, and the refused request that follows is a Failure carrying `insufficient_authorization`, which is a distinct code from the `access_denied` a policy denial returns. That distinction is what lets you show a reviewer which mechanism stopped the call.

## How it works

```
flowchart LR
    A[Revoke the grant] --> B[Keycard]
    C[Agent requests a credential] --> B
    B -->|"no grant to satisfy it"| D["Refused: insufficient_authorization"]
    B --> E[Audit Log]
    D --> E
    F[Credential already held] -.->|"keeps working until it expires"| G[Resource]
```

1. You revoke the grant for that User and Resource, in the Console or through the API.
2. Keycard stops issuing for that pairing. The next exchange fails, and so does a refresh, so the Application cannot quietly extend its access past the credential it currently holds.
3. The Application receives `insufficient_authorization` and should treat it as a prompt to re-authorize rather than as a transient error.
4. The revocation and the refusal are both in the audit trail, and they export to your own bucket alongside everything else.

A credential already in flight keeps working until it expires

Revocation stops Keycard issuing anything new. It does not reach out and invalidate a credential the agent already holds, and there is no per-token kill switch. That token keeps working against the Resource until it expires on its own, so the real containment window is the remaining lifetime of the current credential. Confirm the configured lifetime for your Zone before you describe that window to anyone, because it is the number that decides how long the gap is.

## What you get

One action, in one place, and the next request fails. Nothing is redeployed and no secret is rotated across a fleet.

The evidence is a byproduct rather than an exercise. The withdrawal and the refusal are adjacent records naming the person, the Application, and the Resource, so the question of when access ended is read rather than reconstructed.

Blast radius is bounded even before you act, because credentials expire on their own. Access that nobody renews lapses, which is a different posture from access that persists until someone remembers it.

## What you take on

Containment is bounded by the current credential, not instant. This is the single most important sentence on the page. Where a reviewer needs access to stop within a hard bound, the number that matters is the credential lifetime, and that is a configuration question to settle rather than something to assert.

Revocation is per grant. It is scoped to one User and one Resource, so cutting someone off from everything means either repeating it per Resource or disabling the person, which is a different action with a wider reach.

Brokered access needs a second step. Where the credential came from an external provider such as Google or GitHub rather than being minted by Keycard, revoking the Keycard grant stops Keycard brokering anything new, and it does not revoke what that provider already issued. Cut that off in the provider’s own connected-apps settings as well, or the access continues on the provider’s terms.

A brokered static credential is withdrawn by rotating it. Where Keycard holds a static secret in Vault and hands it to an Application on request, it expires on nobody’s schedule. Rotation remains the mechanism, so plan for it the way you would for any shared secret. [Resources](/concepts/resources/index.md) covers how a vaulted credential differs from an issued one.

## Common questions

### Does revoking kill a session already running?

It stops the next issuance and it stops refresh, so a session cannot extend itself. It does not invalidate the credential already in the agent’s hands, which lives out its remaining lifetime.

### How do we cut one person off from everything at once?

Disabling or removing the person from the People page is the wider lever, and it stops them signing in or obtaining anything new rather than working through grants one Resource at a time. The same boundary applies underneath, so a credential already issued lives out its lifetime either way. [Revoke a Grant](/admin/revoke-a-grant/#cut-a-person-off-entirely/index.md) covers both paths.

### How does a reviewer verify this rather than take our word for it?

Revoke while a session is running and make the next call. It fails with `insufficient_authorization`, and both the revocation and the failure appear in the Audit Log with the person, the Application, and the Resource named. If export is configured, the same records reach your own bucket, so the evidence lives in your infrastructure rather than ours.

### What is the difference between this and a policy denial?

They stop the same call for different reasons and the log distinguishes them. A policy denial returns `access_denied` and the error names the policy and policy set that decided it. A revoked or absent grant returns `insufficient_authorization`, meaning the User has to authorize again. Reading which one you got tells you whether to change a rule or to re-establish consent.

## Where else this applies

- An employee leaving, where the directory change and the grant withdrawal need to agree
- An agent behaving unexpectedly, where you want it stopped before you understand why
- A time-boxed engagement, where access should end on a date rather than when someone remembers
- A compromised host, where the question is what that host can still reach and for how long

The shape is the same each time. Access was granted somewhere specific, it is withdrawn in that same place, and the record of both is the thing you can hand to whoever asks.

## Related

- [Revoke a Grant](/admin/revoke-a-grant/index.md) is the walkthrough, including what happens after you revoke
- [What happens after you revoke](/admin/revoke-a-grant/#what-happens-after-you-revoke/index.md) is the precise behavior, worth reading before you describe it to a reviewer
- [Audit Log & Sessions](/admin/audit-log-and-sessions/index.md) shows how to confirm a revocation took effect
- [Credentials](/concepts/credentials/index.md) explains issuance, refresh, and what a credential is scoped to
- [Access Policies](/admin/access-policies/index.md) is the other way a call gets refused, with a different error code
- [Act as the user who asked](/use-cases/act-as-the-requesting-user/index.md) is the pattern that makes per-user revocation possible in the first place

[Do this ](/admin/revoke-a-grant/index.md)Withdraw an authorization and confirm it in the audit log
