OAuth clients
What OAuth clients are, how AI apps register against your workspace, the authorize flow a user sees, and admin housekeeping.
Admin -> OAuth clients lists every application that has registered to sign users into orboto through OAuth, instead of a long-lived API key - typically an AI client like Claude Desktop, Cursor, or VS Code Copilot connecting to orboto's MCP server.

What an OAuth client is
When an app wants to act on a user's behalf without ever seeing that
user's password, it uses OAuth: the user is sent to orboto's own
login page, logs in there (or is already logged in), sees a consent
screen naming the app and what it's asking for, and - if they approve -
orboto hands the app a short-lived token scoped to that one user. The
app itself, registered ahead of time as an OAuth client, is
identified by a client_id; orboto tracks every client that has ever
completed this flow against your workspace, plus every user who has
individually authorized it.
This matters for security because it means an AI client never needs a copy-pasted, long-lived API key sitting in a config file - each user authorizes their own access, that access can be revoked per user without affecting anyone else connected through the same client, and the whole exchange is visible on this page.
How a client gets here
Two ways a client ends up in the list:
- Auto-registered (dynamic) - most MCP-aware AI clients register
themselves automatically the first time someone points them at your
orboto instance's
/mcpURL and completes the OAuth flow. You don't do anything to make this happen; it shows up on this page once the first user finishes authorizing it. - Operator (pre-seeded) - a client an administrator configures ahead of time rather than letting it self-register. These can only be removed via configuration, not the delete button in this list.
The authorize flow an end user sees
This is what happens on the user's side when they connect an AI client to orboto - useful to know so you can tell a colleague what to expect:
- In the AI client (Claude Desktop, Cursor, VS Code, ...), they add orboto's MCP URL as a new connector/server.
- The client opens a browser to orboto's login page (or reuses an existing session if they're already signed in).
- orboto shows a consent screen naming the requesting app and what it's asking for, plus - where offered - a choice of which identity to connect as: themselves, or an agent account they own.
- They click Authorize. The browser redirects back to the AI client, which now has a working, scoped session.

No API key is copy-pasted anywhere in this flow, and the resulting access token rotates automatically without the user doing anything further. The full connect walkthrough per client (Claude Desktop, Cursor, Copilot, Codex) lives in MCP server setup - this page is the admin side: what shows up here once people have connected, and how to manage it.
What you see per client
Each row shows the client's name and client_id, whether it's
auto-registered or operator, when it was first registered, when
it was last used, and how many users currently have an active
authorization against it.
Click the eye icon on a row to open its authorized-users list - every user with a live grant on that client, when it was issued, and when it expires. From there you can Revoke any individual user's authorization: their next call through that client fails, and they have to go through the consent screen again to reconnect. Revoked authorizations move to a separate section on the same view, tagged with why they were revoked (an admin revoke, the user disconnecting it themselves, the user opting out of MCP entirely, or a security-related token-reuse detection) so you can answer "why did this stop working" without digging through logs.

Scopes
An OAuth grant is scoped, not all-or-nothing: the client only ever
receives an mcp:use-equivalent grant tied to the authorizing user's
own permissions - it can't act with any access the user themselves
doesn't already have. Delegating to an agent account (offered on the
consent screen) attributes the connection's actions, timers, and time
entries to that agent instead of the person authorizing it, and the
connection runs with the agent's own permission set - the person's own
personal timer and timesheet stay untouched. Either way, permission
enforcement happens the same way it does for any logged-in user or API
key: nothing here bypasses orboto's normal access control.
Deleting a client
Deleting an auto-registered (dynamic) client immediately invalidates every user's authorization against it - not just one. A confirmation dialog spells this out before it happens. Operator (pre-seeded) clients can't be deleted from this page at all; that's a deliberate guard against accidentally removing a client your deployment configuration depends on.
Housekeeping: prune unused clients
Over time, dynamic clients that were only ever tried once (or where the integration was abandoned) accumulate. Prune unused dynamic clients removes every dynamic client that currently has zero active authorizations and hasn't been used in 30 or more days - a one-click cleanup that never touches a client anyone is still actively using, and never touches operator-configured clients at all.
Coupling session revoke to MCP grant revoke
By default, force-logging a user out (revoking their login session as an admin) does not also revoke their MCP OAuth grants - a long-running agent process shouldn't be interrupted just because someone force-logged the person out of the web UI elsewhere. The toggle Revoke MCP grants on session revoke changes that: when it's on, an admin force-logout also revokes the user's MCP grants and clears their persisted MCP sessions, so an AI client genuinely can't keep operating after the person is signed out. It's off by default because aggressive revocation interrupts long-running agents; the explicit per-user and per-client Revoke actions above always work regardless of this setting, so you can still revoke a specific grant surgically without flipping the global toggle.

Troubleshooting
- A client I expect to see isn't listed - it only appears after its first user completes the OAuth authorize flow; registering a client doesn't itself create a list entry until someone connects through it.
- Delete is greyed out on a client - it's an operator (pre-seeded) client; those are removed via configuration, not this list, precisely so a deployment's expected clients can't vanish from an accidental click.
- A user says their AI client suddenly can't reach orboto - check their row under that client's authorized-users list; if it's moved to the revoked section, the badge names why (their own disconnect, an admin revoke, an MCP opt-out, or a security-triggered revoke from token-reuse detection).
- Prune unused dynamic clients removed something I still wanted - it only ever removes clients with zero active authorizations that haven't been used in 30+ days; if a client qualified, it genuinely had no active users and no recent activity. Reconnecting simply re-registers it.