> ## Documentation Index
> Fetch the complete documentation index at: https://pipedream.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# How MCP Authorization Works

> Conduit is its own OAuth 2.1 authorization server — how clients register, what the tokens are, and how admins govern them.

Connecting a client is one URL and a browser sign-in — see
[Connect AI Clients](/docs/conduit/use/connect-clients). This page is the layer underneath,
for the people who review it: how clients register, where the tokens come
from, what they can and cannot reach, and the controls an administrator has
over the fleet of connected clients.

## Conduit is the authorization server

Conduit implements the MCP specification's authorization model directly: it
is a full **OAuth 2.1 authorization server**, not a proxy or a pass-through
to your identity provider.

* An unauthenticated request to `/mcp` returns `401` with protected-resource
  metadata, which leads the client to Conduit's authorization-server metadata
  at the standard `.well-known` locations. Clients discover everything;
  nothing is configured client-side but the URL.
* The client walks the authorization-code flow with PKCE:
  authorization request → the person signs in to Conduit — the normal login
  page, [single sign-on](/docs/conduit/configure/sso) included — → an explicit
  consent screen naming the client → code → token. The consent screen cannot
  be embedded by another site, and its Approve action activates only after the
  screen has been visible briefly.
* Every token a client holds is **issued by Conduit**. Your identity
  provider's role is to authenticate the human in the middle of that flow; its
  tokens are never given to MCP clients, and **externally issued tokens are
  not accepted at `/mcp`**. Equivalent controls to a JWT-validating gateway
  are enforced behind the endpoint instead: every request re-validates the
  bearer and the caller's live workspace membership, and every auth event is
  audited.

## How clients register

There are no API keys to create. Clients establish an identity in one of
three ways:

* **Dynamic Client Registration** (RFC 7591) — what most MCP clients do
  (Claude, Cursor, VS Code, and others): the client registers itself at
  `/oauth/register`, unauthenticated, and each registration is a distinct
  client identity per user. Everything such a client says about itself is
  unverified. Whether such clients may connect is each workspace's decision
  (below). Instance admins can additionally **stop accepting new
  registrations** (Settings → Sign-in) once the clients you expect are
  connected, or on instances that want only URL-based client IDs; clients
  already registered keep working.
* **URL-based client IDs** (Client ID Metadata Documents) — the client
  identifies itself by an `https` URL it controls, where its metadata is
  published. One shared identity across all users of that app, and the only
  registration form with a domain-control proof behind it. Conduit accepts
  any `https` client ID; each workspace decides which of these clients may
  reach it (below).
* **The device grant** — the Conduit CLI's `conduit login` shows a short code
  to approve in a browser, on any device. The CLI setup UI is feature-flagged
  and hidden by default.

## The tokens

* **Opaque, not JWTs.** A Conduit token carries no claims to inspect or
  mis-validate; it is a random 256-bit value that Conduit resolves on every
  request. Nothing about a caller's access is decided client-side.
* **Stored hashed.** Like every bearer credential Conduit issues (session
  tokens, refresh tokens, authorization codes), only a one-way hash is stored,
  so a database dump contains nothing replayable.
* **Audience-bound.** A token minted for MCP (RFC 8707 resource binding) is
  valid at `/mcp` and nowhere else — it cannot drive the management API or the
  web UI, and a web session cannot be replayed as an MCP bearer.
* **Short-lived, with rotating refresh.** Access tokens last 24 hours;
  clients refresh silently with single-use refresh tokens that are rotated on
  every use (OAuth 2.1) and expire after 90 days of disuse. Authorization
  codes are single-use and expire in 10 minutes; the device grant's codes
  likewise, though the credential it mints for the CLI lasts 90 days.
* **Revocable immediately.** Revoking a client or a user's sessions takes
  effect on the next request, because every request resolves the token — see
  below. Removing a user from a workspace ends their access on that
  workspace's endpoint the same way, mid-session.

### Scopes limit each client

The consent screen shows a coarse ceiling for the client. The two ordinary
permissions are required; administrative permissions are optional and only
appear when your current role can grant them.

| Scope | What it lets the client use |
| - | - |
| `conduit:connectors` | Tools, prompts, and resources from connectors your workspace policy allows and you have enabled |
| `conduit:user-tools` | Conduit tools for your own account, connections, workspaces, and tool preferences |
| `conduit:workspace-admin` | Workspace administration tools, while you remain an admin of the workspace |
| `conduit:instance-admin` | Instance administration tools, while you remain an instance admin |

Scopes are only a limit on the application. Conduit still checks your live
role and [access policies](/docs/conduit/configure/access-control) on every listing
and direct call, so selecting a scope cannot grant a connector or admin action
you could not otherwise use. A `scopes` entry in client configuration may
limit the optional administrative permissions requested, but the ordinary
permissions remain part of the grant.

Workspace [API clients](/docs/conduit/use/api/scopes) — machine credentials with no
person in the flow — use a separate, finer-grained scope set granted by a
workspace admin at registration; the permissions on this page apply only to
clients a person authorizes interactively.

## Governing connected clients

A token authenticates a person and works at every workspace they belong to
(the URL picks the workspace), so each **workspace** decides which clients may
reach *it* — and which clients it knows.

The instance holds only the one setting that cannot be per workspace: whether
the authorization server accepts new self-registrations at all
([below](#instance-accepting-registrations)).

### Workspace: MCP Clients

**Settings → MCP Clients** (workspace admins, in both deployment shapes) is
two things: who can connect, and one table of clients.

**Who can connect** is one choice among three cards:

* *Any client* (the default). Members connect with whatever they like; you can
  still block a client in the table.
* *Verified clients only*. Clients that prove who they are — URL-based client IDs
  and the Conduit CLI. A self-registered client has no verified identity and is
  blocked unless you allow it.
* *Only allowed clients*. Only the clients you allow connect. A client Conduit
  recognizes starts allowed when it proves who it is — Claude Code, Claude
  Desktop, Codex, ChatGPT and VS Code identify with a published document, and
  Conduit's own CLI is its own — while a client that only registers itself
  (Cursor, MCP Inspector, an install that merely claims to be one of the
  above) is blocked until you allow it in the table's Access column, which is
  also where you take one off.

**Message to blocked members** sits under the cards: the workspace's own words
for a member whose client it blocks — how to get access, whom to ask. Links
work as `[label](https://url)`. Left empty, a blocked member reads only the
posture's own sentence, which the field shows as its placeholder.

**Clients** is the one table, one row per client the workspace has any
relationship with: the clients Conduit recognizes, the ones you added, and
anything that has connected — admitted or refused. A client appears once it
has made a request to *this* workspace (a member's authorization lets a client
reach every workspace they belong to, so only a request says which), or
because Conduit knows it, or because you added it. Facets above the table
select from the same rows: **All**, **Allowed**, **Blocked**, **Connected**.
**Add a client** takes a name and the https URL of the client's client ID
metadata document; only the vendor can host that URL, which is what makes an
install that identifies with it verified, and it is the whole of how Conduit
recognizes the client — a site or a path is refused. A client you add is
decided about on its own, even when its document sits under a vendor Conduit
recognizes: one connector of ChatGPT's, added by its own document URL, is that
row's client rather than ChatGPT's, so it can be blocked while ChatGPT is
allowed, or the reverse. The dialog also sets up
the client's tab on Home: whether it is shown, its icon, and its steps,
prefilled with Conduit's generic ones for you to edit. A client members have
already tried needs no adding: it is a row, and its Access cell lets it in.

Each row shows:

* The client, with its icon, and **Identity**: a blue check when it proves
  who it is (a URL-based client ID, a metadata document only its vendor can
  host, which Conduit fetched and validated — or Conduit's own CLI), a grey
  question mark when it only registered itself and presented signals any client
  could imitate. Claude, Claude Code, ChatGPT, Codex, and VS Code publish such
  documents; Cursor and MCP Inspector connect by registering themselves. A
  recognized client whose members also use installs that merely claim to be it
  gets a second row, *unverified installs*, so each row's mark and Access hold
  for every install behind it.
* **Access** — one word: Allowed; Blocked, for your own decision; or, when
  "Who can connect" is what refuses, the reason itself — Unverified, Not
  allowed. It is a control with three choices: **Workspace default**, shown
  with what "Who can connect" currently gives the client; **Allow**; and
  **Block**, which asks for an optional message that overrides the workspace's
  for this client, shown beside the word as a speech-bubble icon you hover to
  read. Choosing the default drops the client's own decision rather than
  pinning it, so only clients that differ from the posture carry one — and keep
  it when the posture changes. A decision on a client Conduit recognizes covers
  every install recognized as it; on an unknown client it covers clients with
  exactly that identity — which is the client's own claim, so a block on one
  holds only until it registers again under another. To keep self-registering
  clients out for good, use *Verified clients only* or *Only allowed clients*,
  which refuse anything unproven that you have not allowed.
* The leading column — for a client that can be a tab under *How to use
  Conduit* on **Home**, a drag handle and a house: solid while the tab is
  shown, faint while you have hidden it; click to switch. A blocked client has
  no tab while it is blocked, whatever the house says, and gets it back when
  allowed again; hiding an allowed one says nothing about access. The clients with tabs are the
  top rows, in the order members see them; drag a row by its handle (or use
  **Move up** / **Move down** in its menu) to rearrange them. The first shown,
  allowed tab is the one Home opens with. A client with no tab (MCP Inspector,
  the CLI, an unknown client) has neither handle nor house.
* **Members**, **Sessions** and **Last active**: who has connected with the
  client here, their live sessions, and when it was last used in this workspace.

**Edit home page tab** in a row's menu opens the tab as members see it: an
icon (an https image URL; empty for the built-in mark) and the steps, as the
Markdown the page renders, prefilled with what the tab shows today — Conduit's
steps, until you change them — with a live preview. What you save is exactly
what members read, so you can reword a step, point at a managed install, or
replace the steps entirely. Fenced code blocks become copyable commands and
config; `{{server_url}}` stands for the workspace's server URL and
`{{client_name}}` for the client's name, filled in when shown, so the text
never carries a URL that changes per workspace. The steps can't be saved
blank; **Use Conduit's instructions** in the menu brings the shipped steps
back. None of this changes who may connect.

**View members** in a row's menu lists the members using the client, with when
they authorized it, when they were last active here, and their live sessions,
and offers **Revoke** per member or for all: the client stops reaching this
workspace on that member's behalf at once, and access here returns once they
authorize the client again. Nothing is deleted: the member's token keeps
working at their other workspaces until its next refresh, which is refused
while any workspace holds a revocation, so the client returns to the consent
screen — and that approval, which the member gives on their own, lifts the
revocation everywhere. A revocation makes a member re-approve a client; to
keep a client out, block it. **Remove client**
takes a client you added out of the workspace's knowledge, with its tab and any
decision on it.

Members see a block in the client's error and on the consent screen before
they approve (which lists each of their workspaces that will refuse the
client, and offers nothing to approve when none would admit it). The home
page offers setup steps only for the clients the workspace admits: a blocked
client has no tab there, and when "Who can connect" itself refuses clients
the page says so above the tabs, in the posture's sentence and your message.

### Instance: accepting registrations

**Settings → Sign-in** (instance admins) carries the one client setting that
cannot be per workspace: whether clients may register themselves at
`/oauth/register` at all. Registration happens before anyone signs in and
names no workspace, so it is the authorization server's own switch. Turning it
off keeps the registry from filling with unknown clients — new clients must then
identify with a URL-based client ID, and clients already registered keep
working. It does not decide who may connect; each workspace does, and a
workspace that wants no self-registered clients sets *Verified clients only*.

Each user's own sessions can be revoked from **Settings → Users**.

Sign-ins, consents, token grants, and revocations are all audit-logged (a workspace
revoke lands in that workspace's audit log), and rejected MCP requests are
counted by reason in the [metrics](/docs/conduit/deploy/monitoring#gateway) — a burst
of `invalid_token` is either a fleet with stale credentials or someone
guessing.

## Protocol versions

Conduit speaks the stateless MCP revision `2026-07-28` and the handshake
revisions `2025-03-26`, `2025-06-18`, and `2025-11-25`, selected per request;
the [MCP client reference](/docs/conduit/use/mcp-reference) describes how each is
negotiated. Newer-version features — like URL elicitation, which powers the
in-client
[account-connection prompts](/docs/conduit/use/mcp-reference#connecting-your-accounts-from-the-client)
— degrade gracefully for clients that predate them.
