Skip to main content

Resource servers API

REST reference for the resource server lifecycle. Most callers want the first-run guide instead; this page exists for tooling and audit.

The base URL is the AuthSec backend (e.g. http://localhost:7468 in dev, https://api.authsec.dev in prod). All paths below are relative to that.

Auth schemes

Two distinct schemes show up:

  • Admin JWTAuthorization: Bearer <jwt> from the AuthSec admin login flow. For tenant administrators editing setup state.
  • Basic (rs_id : secret)Authorization: Basic <base64(rs_id:introspection_secret)>. For the Go SDK and other resource server callers. The credentials come from the POST /authsec/resource-servers response.

Every endpoint below indicates which.

Lifecycle endpoints

MethodPathAuthPurpose
POST/authsec/resource-serversAdmin JWTRegister a new resource server. Returns Config-ready response.
GET/authsec/resource-serversAdmin JWTList all resource servers for the tenant.
GET/authsec/resource-servers/:idAdmin JWTGet one.
PUT/authsec/resource-servers/:idAdmin JWTUpdate name, base URL, etc.
DELETE/authsec/resource-servers/:idAdmin JWTSoft-delete.
POST/authsec/resource-servers/:id/rotate-introspection-secretAdmin JWTRotate the SDK Basic-auth secret.
POST/authsec/resource-servers/:id/validateAdmin JWTServer-side validation of current setup state.

POST /authsec/resource-servers

Request:

{
"name": "Github MCP Server",
"public_base_url": "https://20-106-226-245.sslip.io",
"protected_base_path": "/mcp",
"scopes_supported": [],
"registration_modes": ["dcr", "cimd", "prereg"]
}

Response (201):

{
"id": "525da3b4-4206-4070-ad68-90cc3a6de43b",
"introspection_secret": "9b7c5e...",
"issuer_url": "http://localhost:7468",
"jwks_uri": "http://localhost:7468/oauth/jwks",
"introspection_endpoint": "http://localhost:7468/oauth/introspect",
"resource_url": "https://20-106-226-245.sslip.io/mcp",
"scope_matrix_url": "http://localhost:7468/authsec/resource-servers/525da3b4-.../sdk-policy",
"manifest_url": "http://localhost:7468/authsec/resource-servers/525da3b4-.../sdk-manifest",
"validation_mode": "auto",
"scopes_supported": [],
"status": "pending_scan"
}

The introspection_secret is only returned here. Lose it → rotate via POST /rotate-introspection-secret.

Setup checklist + activation

MethodPathAuthPurpose
GET/authsec/resource-servers/:id/setupAdmin JWTCurrent setup checklist + can_activate boolean.
GET/authsec/resource-servers/:id/activation-previewAdmin JWTPreview of the policy at the moment of activation.
POST/authsec/resource-servers/:id/activateAdmin JWTFlip state to ready.
POST/authsec/resource-servers/:id/test-loginAdmin JWTSetup signal — OAuth ready, SDK policy state, tool counts.

Tool inventory + scope mapping

MethodPathAuthPurpose
POST/authsec/resource-servers/:id/rescanAdmin JWTTrigger synthetic tools/list against the MCP URL.
GET/authsec/resource-servers/:id/scope-matrixAdmin JWTFull tool-by-scope grid.
POST/authsec/resource-servers/:id/scopesAdmin JWTCreate a custom scope.
PUT/authsec/resource-servers/:id/tool-scope-mapAdmin JWTAssign tools to scopes. Bulk-friendly.
POST/authsec/resource-servers/:id/toolsAdmin JWTManually add a tool not seen in scans.
POST/authsec/resource-servers/:id/tools/:tool_id/publicAdmin JWTMark a tool public.
GET/authsec/resource-servers/:id/sdk-manifest-statusAdmin JWTWhether the SDK has pushed a manifest, and validation status.

SDK-facing endpoints (Basic auth)

The three endpoints your Go SDK uses at runtime:

MethodPathAuthPurpose
POST/oauth/introspectBasic (rs_id : secret)RFC 7662 token introspection. Returns RBAC-resolved scopes.
GET/authsec/resource-servers/:id/sdk-policyBasic (rs_id : secret)Compiled tool→scope map for runtime enforcement.
PUT/authsec/resource-servers/:id/sdk-manifestBasic (rs_id : secret)Push tool inventory from the SDK.

POST /oauth/introspect

Request (form-encoded):

token=eyJhbGc...

Response:

{
"active": true,
"sub": "alice@example.com",
"aud": "https://your-mcp.example.com/mcp",
"scope": "rs-xyz:tools:read rs-xyz:tools:write",
"exp": 1730000000,
"client_id": "claude-desktop"
}

The returned scope is RBAC-resolved: it's filtered to what the user is currently allowed to have, not what the token was originally issued with. See Token introspection vs JWT.

GET /authsec/resource-servers/:id/sdk-policy

Response:

{
"scope_matrix": {
"echo_read": ["rs-xyz:tools:read"],
"echo_write": ["rs-xyz:tools:write"],
"health": []
},
"drift_events": []
}

Empty array for a scope means public. Tool absent from the map is denied (assuming any policy is in effect).

Access policy

MethodPathAuthPurpose
GET/authsec/resource-servers/:id/access-policyAdmin JWTDefault role + first-time-user grant config.
PUT/authsec/resource-servers/:id/access-policyAdmin JWTUpdate.

Clients

MethodPathAuthPurpose
GET/authsec/resource-servers/:id/clientsAdmin JWTList OAuth clients registered against this RS.
POST/authsec/resource-servers/:id/clientsAdmin JWTPre-register a client.
PUT/authsec/resource-servers/:id/clients/:client_id/approve-redirectsAdmin JWTApprove pending redirect-URI changes (CIMD).

Monitor / drift events

MethodPathAuthPurpose
GET/authsec/resource-servers/:id/drift-eventsAdmin JWTPost-activation policy changes.
POST/authsec/resource-servers/:id/drift-events/:event_id/dismissAdmin JWTAcknowledge an event.

Event types: scope_deleted, tool_unmapped, default_role_disabled, default_role_changed, secret_rotated. See states and events reference for payload shapes.

Error responses

OAuth endpoints return RFC 6749 shaped errors:

{
"error": "invalid_request",
"error_description": "human readable explanation"
}

Non-OAuth admin endpoints return a simpler shape:

{ "error": "tenant_id required in JWT" }

Standard HTTP status codes apply throughout.