Skip to main content

Resource types and resource servers

Use this page to register a kind of data that clients ask for tokens to, when it is not a managed resource. Registering a managed resource or connecting a connector does these steps for you.

  • A resource type names a kind of data, such as urn:example:invoices, and the scopes that apply to it.
  • A resource server maps an API's URL, its resource indicator, to one or more resource types.

Register a resource type​

curl -fsS -X POST "$POLICYARC_URL/admin/api/resource-types" \
-H "X-Admin-API-Key: $POLICYARC_ADMIN_KEY" \
-H 'Content-Type: application/json' \
-d '{"typeUri": "urn:example:invoices", "name": "Invoices", "scopes": ["invoices:read"]}'

The response is HTTP 201. The call also adds the type and its scopes to the pbac.operator.controls.resource_registry row, which is what policy reads.

These types exist on every environment.

TypeScopesFor
urn:as:userinfoopenid, profile, email/userinfo
urn:as:introspectuma_protection, introspectionCalling /introspect
urn:as:authzenauthzenCalling /access/v1/evaluation
urn:mcp:servermcp:tools, mcp:resourcesThe MCP endpoint /gateway/mcp

Register a resource server​

curl -fsS -X POST "$POLICYARC_URL/admin/api/resource-servers" \
-H "X-Admin-API-Key: $POLICYARC_ADMIN_KEY" \
-H 'Content-Type: application/json' \
-d '{"resourceIndicator": "https://api.example.com/invoices/*", "name": "Invoices API", "typeUris": ["urn:example:invoices"], "enabled": true}'

A /* at the end matches any path below. When several indicators match, the longest one wins.

Ask for a token by URL or by type​

A client names the resource with the resource parameter, its URL. The server finds the resource server and so the type.

The client needs the type and scope in its entitlements first. This call sets the entitlement of the client from Register a managed resource and replaces what it had.

curl -fsS -X PATCH "$POLICYARC_URL/admin/api/policy-data/by-key?dataKey=pbac.operator.controls.client_entitlements&path=client_id.$CLIENT_ID" \
-H "X-Admin-API-Key: $POLICYARC_ADMIN_KEY" \
-H 'Content-Type: application/json' \
-d '{"grant_types": ["client_credentials"], "granted_resources": [{"type": "urn:example:invoices", "scopes": ["invoices:read"]}]}'

The block waits a few seconds for the policy engine, then asks for a token by URL.

sleep 5
curl -fsS -u "$CLIENT_ID:$CLIENT_SECRET" "$POLICYARC_URL/token" \
-d grant_type=client_credentials -d scope=invoices:read \
-d resource=https://api.example.com/invoices/7

What we saw.

RequestResult
resource=https://api.example.com/invoices/7A token. Introspected, it has resource_types: ["urn:example:invoices"] and extensions.granted_resource set to the URL.
resource=https://nowhere.example.com/xHTTP 400 {"error":"invalid_target","error_description":"Resource could not be resolved to a known type"}
The same URL plus resource_types=urn:example:invoicesA token. The type parameter names the type directly.
resource_types=urn:example:invoices and scope=invoices:deleteHTTP 400 access_denied. Neither the type nor the client's entitlement has that scope.