Skip to main content

Manage Resource Servers

A resource server in ThunderID represents an API, service, or application that defines the permissions your users and clients can request. Before you assign permissions to users through roles, you define those permissions by creating resource servers with resources and actions.

Prerequisites

  • A running ThunderID instance.
  • An organization unit to associate the resource server with. See Organization Units to create one.
  • An access token with administrative permissions.

Understanding the Permission Model

ThunderID derives permission strings from a three-level hierarchy:

Resource Server (identifier: "https://api.example.com/booking", delimiter: ":")
├── Action: "list" → Permission: "list"
└── Resource: "reservations"
├── Action: "create" → Permission: "reservations:create"
├── Action: "view" → Permission: "reservations:view"
└── Resource: "online"
└── Action: "create" → Permission: "reservations:online:create"

Permission strings use one of two forms. Flat permissions, for server-level actions, are just the {action-handle} (for example, list). Hierarchical permissions follow {resource-handle}{delimiter}{action-handle} (for example, reservations:create). Permission strings are not prefixed by the resource server; the resource server is identified by its identifier, which becomes the access token audience.

  • Resource Server: container for all resources and actions. Requires a unique identifier. When the identifier is set to an absolute URI, the resource server is used in resource indicator flows (RFC 8707).
  • Resource: a named entity within a resource server. Resources can nest to form hierarchies.
  • Action: an operation that can be performed. Actions can exist at the resource server level (global) or within a specific resource.

Create a Resource Server

Send a POST request to /resource-servers:

curl -kL -X POST https://localhost:8090/resource-servers \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-token>' \
-d '{
"name": "Booking API",
"description": "Handles reservation operations",
"identifier": "https://api.example.com/booking",
"ouId": "<organization-unit-id>",
"delimiter": ":"
}'

Response:

{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "Booking API",
"description": "Handles reservation operations",
"identifier": "https://api.example.com/booking",
"ouId": "a839f4bd-39dc-4eaa-b5cc-210d8ecaee87",
"delimiter": ":"
}

Field Reference

FieldRequiredDescription
nameYesDisplay name for the resource server. Must be unique.
identifierYesUnique identifier for the resource server. When set to an absolute URI (for example, https://api.example.com/booking), the resource server is used in RFC 8707 resource indicator flows and the identifier becomes the access token audience claim value.
ouIdYesOrganization unit ID.
delimiterNoCharacter that separates hierarchy levels in permission strings. Defaults to :. Immutable after creation. Allowed characters: a-z A-Z 0-9 . _ : - /.
descriptionNoDescription of the resource server.
note

The delimiter field cannot be changed after creation. Plan this value before creating the resource server.

Define Permissions

You define permissions by creating actions. Actions can exist at two levels: directly on the resource server (flat permissions) or on a resource within the server (hierarchical permissions).

Flat Permissions

Create actions directly on the resource server for simple, non-hierarchical permissions.

curl -kL -X POST https://localhost:8090/resource-servers/<resource-server-id>/actions \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-token>' \
-d '{
"name": "List Bookings",
"description": "Permission to list all bookings",
"handle": "list"
}'

Response:

{
"id": "9c6d3g0g-7e8b-4d82-b454-4d2ccg87gh5e",
"name": "List Bookings",
"description": "Permission to list all bookings",
"handle": "list",
"permission": "list"
}

The resulting permission is list. A server-level action is just the action handle.

Hierarchical Permissions

For fine-grained access control, create resources first, then add actions to those resources.

1. Create a resource:

curl -kL -X POST https://localhost:8090/resource-servers/<resource-server-id>/resources \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-token>' \
-d '{
"name": "Reservations",
"handle": "reservations"
}'

2. Add an action to the resource:

curl -kL -X POST https://localhost:8090/resource-servers/<resource-server-id>/resources/<resource-id>/actions \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-token>' \
-d '{
"name": "Create Reservation",
"handle": "create"
}'

The resulting permission is reservations:create.

3. Create nested resources (optional):

Resources can nest to form deeper hierarchies. Set the parent field to the parent resource ID:

curl -kL -X POST https://localhost:8090/resource-servers/<resource-server-id>/resources \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-token>' \
-d '{
"name": "Online Reservations",
"handle": "online",
"parent": "<reservations-resource-id>"
}'

Actions on this nested resource produce permissions like reservations:online:create.

note

The handle and parent fields on a resource are immutable after creation.

List Resource Servers

curl -kL https://localhost:8090/resource-servers?limit=10&offset=0 \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <access-token>'

Get Resource Server Details

curl -kL https://localhost:8090/resource-servers/<resource-server-id> \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <access-token>'

Update a Resource Server

Update the name, description, identifier, or organization unit. The delimiter cannot be changed.

curl -kL -X PUT https://localhost:8090/resource-servers/<resource-server-id> \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-token>' \
-d '{
"name": "Booking API v2",
"description": "Updated booking operations",
"identifier": "https://api.example.com/booking/v2",
"ouId": "<organization-unit-id>"
}'

Delete a Resource Server

curl -kL -X DELETE https://localhost:8090/resource-servers/<resource-server-id> \
-H 'Authorization: Bearer <access-token>'
note

You must delete all child resources and actions before you can delete a resource server.

Manage Resources

List Resources

List top-level resources (no parent):

curl -kL https://localhost:8090/resource-servers/<resource-server-id>/resources \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <access-token>'

List child resources of a specific parent:

curl -kL "https://localhost:8090/resource-servers/<resource-server-id>/resources?parentId=<parent-resource-id>" \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <access-token>'

Update a Resource

You can update the name and description. The handle and parent cannot be changed.

curl -kL -X PUT https://localhost:8090/resource-servers/<resource-server-id>/resources/<resource-id> \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-token>' \
-d '{
"name": "Updated Reservations",
"description": "Updated description"
}'

Delete a Resource

curl -kL -X DELETE https://localhost:8090/resource-servers/<resource-server-id>/resources/<resource-id> \
-H 'Authorization: Bearer <access-token>'

You must delete all sub-resources and actions within a resource before deleting it.

Manage Actions

List Actions

List resource server level actions:

curl -kL https://localhost:8090/resource-servers/<resource-server-id>/actions \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <access-token>'

List actions on a specific resource:

curl -kL https://localhost:8090/resource-servers/<resource-server-id>/resources/<resource-id>/actions \
-H 'Accept: application/json' \
-H 'Authorization: Bearer <access-token>'

Update an Action

You can update the name and description. The handle cannot be changed.

curl -kL -X PUT https://localhost:8090/resource-servers/<resource-server-id>/actions/<action-id> \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access-token>' \
-d '{
"name": "Updated Action Name",
"description": "Updated description"
}'

Delete an Action

curl -kL -X DELETE https://localhost:8090/resource-servers/<resource-server-id>/actions/<action-id> \
-H 'Authorization: Bearer <access-token>'

Best Practices

  • Plan handle names before creation. The handle on resources and actions is immutable, as is the resource server delimiter. Use lowercase with hyphens for readability (for example, reservations, create).
  • Use absolute URIs as identifiers for RFC 8707. The identifier field accepts any string, but only resource servers with absolute URI identifiers (such as https://api.example.com/booking) are used in resource indicator flows. Set a URI identifier if you need audience-restricted access tokens.
  • Create one resource server per API boundary. Separate resource servers for different microservices or applications produce cleaner permission models and more targeted access tokens.
  • Choose the delimiter before creation. The delimiter separates hierarchy levels in permission strings and cannot be changed. The colon (:) is the most common choice.

Next Steps

Explore with AI

ThunderID LogoThunderID Logo

Product

DocsAPIsSDKs
© Copyright Linux Foundation Europe.For web site terms of use, trademark policy and other project policies please see https://linuxfoundation.eu/en/policies.