Overview

Permissions are the most granular building blocks of the Enterprise Stack RBAC model. Each protected operation on a resource is tied to a specific permission, enabling fine-grained control across different levels of the system. Permissions can be:

  • Creating a key
  • Creating a Decentralized Identifier (DID)
  • Deleting an API key
  • Updating tenant configuration

Example of an enterprise resource tree:

Example Enterprise Resource Tree

The Enterprise Stack Permissions implements Hierarchical Access Control with Inheritance and Explicit Deny.

Permission Scope

Next to the permission itself, there is the level to which the permission must be applied (the scope). For example, a permission could be applied on an organizational or a tenant level thereby granting the permission on all sub-resources of that organization or tenant. The assignment of the level happens during role creation. Roles are the way permissions get assigned to API-Keys or Accounts.

In a tree-structured resource hierarchy, permissions follow a Top-Down logic.

Propagation

When a permission is granted at a parent node (e.g., a organization root folder), it automatically "flows down" to all child nodes and sub-branches (tenants, enterprise services, resources). This allows administrators to manage access for thousands of resources by setting a single rule at a high level, rather than configuring each leaf node individually.

The "Explicit Deny" Mechanism

To allow for granular control and security exceptions, the system supports an Override function. Even if a user has inherited "Allow" from a parent, a specific "Deny" can be placed on any sub-branch or individual resource. A Deny always overrides an Allow. This ensures that if access is restricted for a specific sensitive sub-branch, no higher-level permission can accidentally grant access to it.

This is particularly useful when using a wildcard permission. A wildcard permission like ALL enables a user to do all operations under the specified scope (e.g. Organization or Tenant). Therefore, revoking a particular permission could be used to decrease the amount of actions a user can perform.

Example Scenario

  • Tenant Admin A is granted ALL on Tenant A.
    He can use KMS and Issuer Enterprise Service of Tenant A
  • Issuer User is granted ISSUE_CREDENTIAL on Tenant A
    He can issue credential with all Issuer Enterprise Services in of Tenant A
    He is not allowed to read or generate keys by using the KMS

Permission Evaluation Logic

When a user attempts to access a resource, the system evaluates the "Effective Permission" using these steps:

  1. Does the user have specific ALLOW for this resource or parent resource?
    If no, access to the resource is rejected if yes, continue with step 2
  2. Does the user have specific DENY for this resource or parent resource?
    If yes, access to the resource is rejected
  3. If access is allowed but not denied, access to resource is granted

Wildcards

  • ALL - Enables a user to do all operations under the specified scope.

Assigning permissions to a role

Create role waltid.test.issuer-role with permission issuer-credential-issue on resource waltid.test.issuer1


curl -X 'POST' \
  'https://waltid.enterprise.demo.walt.id/v1/waltid.test.issuer-role/roles-api/roles/create' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer "some-token' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "Issuer 2 Role",
  "permissions": [
    {
      "target": "waltid.test.issuer1",
      "action": "issuer-credential-issue"
    }
  ]
}'

Permissions can be added to already existing roles. Add permission issuer-credential-issue on resource waltid.test.issuer1 to role waltid.test.issuer-role

curl -X 'POST' \
  'https://waltid.enterprise.demo.walt.id/v1/waltid.test.issuer-role/roles-api/permissions/permissions/add-to-role' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer "some-token"' \
  -H 'Content-Type: application/json' \
  -d '{
  "target": "waltid.test.issuer1",
  "action": "issuer-configuration-display-view"
}'

Revoking permissions from a role (with Deny rule)

Deny all users with role waltid.admin to issue credential with any issuer service of watid.test tenant

curl -X 'POST' \
  'https://waltid.enterprise.demo.walt.id/v1/waltid.admin/roles-api/permissions/permissions/add-to-role' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer "someToken' \
  -H 'Content-Type: application/json' \
  -d '{
  "target": "waltid.test",
  "action": "issuer-credential-issue"
  "operation": "REMOVE"
}'

Even if the user has permission to issue credentials granted by some role, the deny rule added to role waltid.admin will reject the operation

Permissions Available

You can find the required permissions for the various API endpoints by visiting the SWAGGER documentation. In the description of each endpoint, look for a field labeled "Operation." This field indicates the specific permission needed to access that endpoint.

Visit the SWAGGER docs here.

Last updated on April 8, 2026