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.
| Type | Scopes | For |
|---|---|---|
urn:as:userinfo | openid, profile, email | /userinfo |
urn:as:introspect | uma_protection, introspection | Calling /introspect |
urn:as:authzen | authzen | Calling /access/v1/evaluation |
urn:mcp:server | mcp:tools, mcp:resources | The 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.
| Request | Result |
|---|---|
resource=https://api.example.com/invoices/7 | A token. Introspected, it has resource_types: ["urn:example:invoices"] and extensions.granted_resource set to the URL. |
resource=https://nowhere.example.com/x | HTTP 400 {"error":"invalid_target","error_description":"Resource could not be resolved to a known type"} |
The same URL plus resource_types=urn:example:invoices | A token. The type parameter names the type directly. |
resource_types=urn:example:invoices and scope=invoices:delete | HTTP 400 access_denied. Neither the type nor the client's entitlement has that scope. |
Send feedback about this page