Pre-register OAuth clients
The Clients tab lists every OAuth client that's allowed to call your MCP server. Most clients register themselves via DCR; this tab exists for the cases where you need to do it manually.
What the UI does
You see two kinds of entries:
- Dynamic (DCR) — registered themselves by hitting
POST /oauth/registerat runtime. Auto-approved. Shown as approved with their assignedCLIENT_ID. - Pre-registered — created by an admin via this tab or the API. Same data model, just a different
registration_type.
The example screenshot shows 30 DCR clients (Claude Code instances connecting from various github-remote workspaces, plus one Codex client). All APPROVED. This is the normal state of the world.
When do you need to pre-register?
Three cases:
- You're testing with curl or a CLI that doesn't speak DCR. Pre-register once, hard-code the
client_idandclient_secretin your test script. - You're integrating a server-to-server client (a CI job, an internal service) that doesn't have a UI for the OAuth dance. The pre-registered client uses the client_credentials grant.
- You want to constrain redirect URIs in advance. DCR accepts any redirect URI the client claims; pre-registration lets you whitelist exactly what's allowed.
For everything else — Claude Desktop, Codex, any MCP client that supports DCR — skip pre-registration. The DCR auto-approval flow handles it.
DCR (Dynamic Client Registration)
MCP clients that support DCR will hit POST /oauth/register with a JSON body like:
{
"client_name": "Claude Code",
"redirect_uris": ["http://localhost:33417/oauth/callback"],
"grant_types": ["authorization_code", "refresh_token"]
}
AuthSec creates a mcp_oauth_clients row, generates a client_id, and returns the registration. The row goes into resource_server_client_registrations with status = 'approved' — DCR is auto-approve by default. The client immediately starts the authorization-code flow with the returned client_id.
The Clients tab shows these as APPROVED with the registration mode tag Dynamic (DCR).
CIMD (Client-Initiated Manifest Delivery)
A variant of DCR where the client hosts a public JSON document describing itself (its name, logo, redirect URIs, etc.), and registration just points at that URL. When the client wants to change its redirect URIs later, it updates the manifest; AuthSec polls and stages the change as a pending_redirect_uris update that the admin approves.
Useful for OS-distributed MCP clients (like Claude Desktop installed via the App Store) where the redirect URI list changes when new versions ship.
Admin approval flow: PUT /authsec/resource-servers/:id/clients/:client_id/approve-redirects.
Pre-registration via API
curl -X POST "https://api.authsec.dev/authsec/resource-servers/$RS/clients" \
-H "Authorization: Bearer $ADMIN_JWT" \
-H "Content-Type: application/json" \
-d '{
"client_name": "my-ci-job",
"redirect_uris": ["https://ci.example.com/oauth/callback"]
}'
Returns:
{
"client_id": "abc-123",
"client_secret": "...",
"redirect_uris": ["https://ci.example.com/oauth/callback"],
"registration_type": "prereg"
}
The client_secret is only returned in this response. Treat it like a password.
Registration modes
The resource server has a registration_modes array that controls which modes are allowed. Default is ['dcr', 'cimd', 'prereg'] — all three. To disable DCR (require pre-registration for everyone), edit the resource server and remove dcr from the list.
Auth scheme
| Endpoint | Auth | Caller |
|---|---|---|
POST /oauth/register (DCR) | None (open by default) | OAuth client itself |
POST /authsec/resource-servers/:id/clients (pre-reg) | Admin JWT | Tenant admin / UI |
GET /authsec/resource-servers/:id/clients | Admin JWT | Tenant admin / UI |
PUT /authsec/resource-servers/:id/clients/:client_id/approve-redirects | Admin JWT | Tenant admin / UI |
Note that DCR is unauthenticated — anyone can register a client. The trust boundary is the OAuth flow itself (a registered client still has to get a user to consent to scopes).
Related
- Access policy and default role — the previous step
- Run the protection test — the next step