Revocation and Offboarding for MCP Servers: What Happens After a User Is Disabled

Most MCP authorization work stops at the moment a token is issued. Reviews do not. Somewhere in a vendor security questionnaire there is a question in the shape of: when we disable an employee in our identity provider, how long can their agent keep calling your server? If the honest answer is "up to an hour, and their refresh token still works for thirty days", say so before the reviewer finds out. Then fix it.

This is a guide to the revocation side of the MCP authorization specification: what the OAuth RFCs give you, what your server has to do itself, and what to write down.

The question behind the question

Offboarding is the reviewer's proxy for a broader concern: access granted to an agent is access granted to software that keeps running when nobody is looking. A human who is locked out stops working. An agent with a valid refresh token does not. So the reviewer is really asking three things:

  1. How long is a leaked or stale access token useful?
  2. Can you cut off a specific user, a specific client, or a specific grant on request, and how fast?
  3. Would you know it happened, and could they see it in their own logs?

Each one is answerable with existing standards. None of them is answered by the MCP specification alone, because the specification makes your server a resource server and leaves token lifecycle to the authorization server.

Access token lifetime is your blast radius

An access token that your MCP server accepts is a bearer credential. Between issuance and expiry, the only thing standing between a copied token and your data is whatever validation you do on each call.

Two practical positions:

  • Short access tokens, refreshed often. Minutes, not hours. The client library handles refresh; MCP clients are OAuth clients and are expected to. Short lifetimes mean an IdP-side disable takes effect on the next refresh, without your server doing anything clever.
  • Introspect on every call. RFC 7662 token introspection asks the authorization server whether a token is still active. It is correct, it is immediate, and it puts your authorization server in the hot path of every tool call. Cache the result for seconds if you must, and state the cache window in your documentation, because the cache window is the revocation delay.

A reasonable default for a B2B SaaS MCP server: short-lived signed access tokens validated locally, plus introspection on the tools that can change state. Write down the number. "Access tokens live five minutes; a disabled user's agent loses access within five minutes" is a sentence that closes a questionnaire item. "We use OAuth" is not.

If you use sender-constrained tokens, this gets better rather than shorter. Constraining a token to the client's key (DPoP, or mTLS-bound tokens per RFC 8705) means a copied token is not usable on its own. That is a stronger answer than a short lifetime, and it does not remove the need for revocation.

Refresh tokens are the part people forget

The long-lived credential in an MCP setup is almost never the access token. It is the refresh token sitting in the agent host's credential store, on a laptop, for weeks.

What the OAuth 2.1 draft and the security best current practice (RFC 9700) expect:

  • Refresh tokens issued to public clients must be sender-constrained or rotated on every use. Rotation is the common choice: each refresh returns a new refresh token and invalidates the old one.
  • Reuse of a rotated refresh token is an attack signal. The correct response is to invalidate the whole grant family, not just reject the call. Then emit an audit event, because that event is the one a customer's security team will want.
  • Refresh tokens need an absolute expiry as well as an idle expiry. Otherwise an agent configured once in March still holds access in December.

If your authorization server is a commercial IdP, most of this is a configuration screen. Go and look at what it is actually set to before you claim it in a document.

Revocation endpoints, and who is allowed to call them

RFC 7009 defines the token revocation endpoint. It lets a client discard its own tokens, which is the right thing to call when a user disconnects your server in their agent host, or when the host uninstalls the connector.

Two limits worth stating plainly:

  • RFC 7009 is client-initiated. It does not help when the client is the thing you no longer trust. Administrative revocation — kill every grant for this user, or every grant for this client — is an authorization server management function, not a standard endpoint. Know how to do it in your IdP, and know how long it takes to propagate to signed tokens already in the wild.
  • Revoking a token does not undo what it did. Revocation is containment; the audit trail is what tells the customer the scope of the incident.

Your MCP server should also offer a way for a user to see and drop their own connections. A short list of "agent clients currently authorized on your account, with last-used time, and a revoke button" answers several questionnaire items at once and costs a day.

Downstream tokens die too

If your server does token exchange (RFC 8693) to call your own API or a third party on the user's behalf, revocation has to reach those tokens as well. A revoked upstream grant with a still-valid downstream token is a confused deputy with a longer fuse.

Rules that hold up:

  • Downstream tokens are derived per request and live no longer than the incoming token's remaining validity. Do not cache them past that.
  • If you store third-party credentials from an account-linking flow, deletion of the user's grant must delete those stored credentials, and the deletion must be recorded.
  • Never keep a service credential that can act for a user who no longer exists. Enumerate what your server holds that outlives a session; that inventory belongs in the threat model.

Getting the signal earlier

Short lifetimes and introspection both make revocation a matter of waiting. Enterprise customers with mature identity teams increasingly want it to be a matter of being told.

The relevant work is the OpenID Shared Signals Framework and its CAEP event profile: an identity provider pushes events such as session revoked, credential change, or assurance level change to a receiver, which reacts. OpenID Connect back-channel logout covers the narrower session case. SCIM (RFC 7644) covers deprovisioning of the account record itself.

Be honest about maturity here. Most MCP servers do not need a shared-signals receiver, and building one before you have a customer asking for it is misplaced effort. What you should do now is make revocation a single code path in your server — one function that, given a user or a grant, invalidates cached introspection results, drops derived downstream tokens, terminates open sessions and streams, and emits an audit event. Once that path exists, wiring a new trigger to it later is small. If it does not exist, every new trigger is a project.

Terminating work in flight

MCP sessions are long-lived, and a streamable HTTP connection can outlive the token that opened it. Revocation that only affects the next request is incomplete.

Design for this explicitly:

  • Bind the session to the grant, and check validity at the start of every tool call rather than only at session establishment.
  • When a grant is invalidated, close the session's open streams and return an authorization error, so the host prompts the user to re-authorize instead of silently retrying.
  • Cancel or fail in-flight long-running tool calls belonging to that grant. A background job that finishes after offboarding, using data the user no longer has rights to, is exactly the finding that reopens a closed review.

What to write down

The deliverable is a page in the evidence pack, not a paragraph of reassurance. It should state:

  • Access token lifetime, refresh token rotation policy, idle and absolute refresh expiry, all as numbers.
  • Validation method per tool class, and the introspection cache window if there is one.
  • The revocation paths that exist: user self-service, client-initiated per RFC 7009, administrative per-user and per-client, and the expected time to effect for each.
  • What happens to derived and stored downstream credentials.
  • The audit events emitted on authorization failure, refresh reuse, and revocation, and how the customer can receive them.
  • What you do not do yet. If you have no shared-signals receiver, say that, and say what the customer can do instead.

A reviewer who reads that page stops asking about offboarding. A reviewer who reads "tokens are revoked promptly" asks four more questions and books a call.

Where this usually lands

In our experience the token lifetime settings are easy and the in-flight termination is not, because it requires the server to carry grant identity into every handler and every background task. That is the same plumbing that makes per-user scoping and usable audit events work, which is why we treat all three as one design decision rather than three features.

If you want an independent read on how your server behaves after a user is disabled, that is part of what an MCP security audit covers, and it is standard scope on a server build.