Roles and Permissions Compatibility¶
Authifi uses one authorization model for current integrations:
- Access Roles (
AccessRole) group permissions for an authorization context. Some UI screens still label these API Roles. - Resource Server Permissions (
ResourceServerPermission) represent fine-grained permissions. /access-rolesmanages Access Roles./resource-servers/{resourceServerId}/permissionsmanages permissions.- Ordinary API access tokens carry granted Resource Server Permissions in the
scopeclaim. - Trusted UserInfo and server-side session claims can carry
resource_roles, keyed by resource server identifier.
An OAuth client can have a linked or auto-generated resource server, so application-assigned authorization and standalone API authorization use the same Access Role and Resource Server Permission entities.
Client permissions means Resource Server Permissions on an OAuth client's auto-generated placeholder resource server.
Client credential roles and permissions means Access Roles marked for client credential grants, their Resource Server Permissions, and the associated client — authorization assigned to applications rather than users.
For current configuration guidance, see the SSO Integration Guide and OIDC Request Scopes.
All routes below are relative to /auth/admin/tenants/{tenantId} unless the full path is shown.
Deprecated role route family¶
The /roles controller is a deprecated wrapper over AccessRole that maps legacy role shapes to the unified store. POST /roles requires a client and creates the Access Role on that client's linked or auto-generated resource server. The remaining wrapper is broader than an application-only view:
GET /rolesreturns tenant Access Roles across client-linked and standalone resource servers unless the caller supplies aclientIdfilter.GET /roles/countand the read, update, replace, and delete routes keyed by role ID constrain by tenant, but do not require the Access Role to be client-associated.- Role-permission relation routes likewise operate on the unified tenant
AccessRoleandResourceServerPermissionrecords while returning legacy shapes.
Use the canonical routes for new integrations so the resource-server context is explicit. Do not rely on /roles to enforce an application-only boundary.
| Deprecated route | Canonical replacement |
|---|---|
POST /roles |
POST /access-roles |
GET /roles |
GET /access-roles |
GET /roles/count |
GET /access-roles/count |
GET /roles/{id} |
GET /access-roles/{id} |
PATCH /roles/{id} |
PATCH /access-roles/{id} |
PUT /roles/{id} |
PUT /access-roles/{id} |
DELETE /roles/{id} |
DELETE /access-roles/{id} |
GET /roles/{roleId}/permissions |
GET /access-roles/{accessRoleId}/resource-server-permissions |
PUT /roles/{roleId}/permissions/rel/{permissionId} |
PUT /resource-servers/{resourceServerId}/permissions/{permissionId}/access-roles/rel/{accessRoleId} |
DELETE /roles/{roleId}/permissions/rel/{permissionId} |
DELETE /resource-servers/{resourceServerId}/permissions/{permissionId}/access-roles/rel/{accessRoleId} |
The relation replacements require the Resource Server Permission's resourceServerId; the legacy route inferred the application resource context.
Deprecated permission route family¶
The /permissions controller is a deprecated wrapper over ResourceServerPermission. It resolves the legacy application context to the client's resource server.
| Deprecated route | Canonical replacement |
|---|---|
POST /permissions |
POST /resource-servers/{resourceServerId}/permissions |
GET /permissions |
GET /resource-servers/{resourceServerId}/permissions |
GET /permissions/count |
GET /resource-server-permissions/count with an appropriate filter |
GET /permissions/{id} |
GET /resource-servers/{resourceServerId}/permissions/{permissionId} |
PATCH /permissions/{id} |
PATCH /resource-servers/{resourceServerId}/permissions/{permissionId} |
PUT /permissions/{id} |
PATCH /resource-servers/{resourceServerId}/permissions/{permissionId} |
DELETE /permissions/{id} |
DELETE /resource-servers/{resourceServerId}/permissions/{permissionId} |
DELETE /permissions |
No canonical bulk-delete route; list the resource server permissions and delete each by ID |
Deprecated relation and legacy views¶
These implemented routes expose legacy application-role names or shapes over the unified stores:
| Deprecated route | Canonical replacement |
|---|---|
PUT /groups/{groupId}/roles/rel/{roleId} |
PUT /groups/{groupId}/access-roles/rel/{accessRoleId} |
DELETE /groups/{groupId}/roles/rel/{roleId} |
DELETE /groups/{groupId}/access-roles/rel/{accessRoleId} |
GET /groups/{groupId}/roles |
GET /groups/{groupId}/access-roles |
GET /clients/{id}/roles |
GET /access-roles filtered by clientId |
GET /users/{userId}/permissions |
GET /users/{userId}/resource-server-permissions |
GET /users/{userId}/roles |
Group-inherited Access Roles: get the user's groups, then GET /groups/{groupId}/access-roles. Direct user-role assignments have no separate canonical list endpoint; prefer group-assigned Access Roles for new integrations, or retain the deprecated route until those assignments are migrated. |
GET /users/{userId}/app-and-api-roles |
Get group Access Roles, then their Resource Server Permissions |
POST /client/{clientId}/users-with-set-of-app-permissions |
No resource-scoped canonical set-query; see below |
GET /users-with-app-permissions/{permissionId} |
GET /users-with-api-permissions/{permissionId} |
GET /users/count-users-with-app-permissions/{permissionId} |
GET /users/count-users-with-api-permissions/{permissionId} |
GET /users-with-app-roles/{roleId} |
GET /users-with-api-roles/{roleId} |
GET /users/count-users-with-app-roles/{roleId} |
GET /users/count-users-with-api-roles/{roleId} |
Do not use the deprecated wrappers or flat claims for new integrations.
The deprecated POST /client/{clientId}/users-with-set-of-app-permissions route is not equivalent to POST /users-with-set-of-api-permissions. The deprecated route constrains Access Roles by clientId. The canonical API permission-name query aggregates matches across the tenant and has no resource server filter. Because permission names are unique only within a resource server, it can combine same-named permissions from different APIs.
Until a canonical resource-scoped set-query exists, existing consumers that need the exact client-specific result may retain the deprecated route. New integrations should resolve the client's linked Resource Server, resolve every permission by exact name within that Resource Server, list Access Roles for that resource context, and traverse their group and user assignments. Include a user only when that one resource context grants the complete requested permission set. Do not substitute the tenant-wide permission-name query.
Deprecated claim compatibility¶
The enableLegacyRoles client feature toggle enables projection of flat roles and access_roles claims for older consumers. These claims discard the resource server boundary and can collide when resources use the same role name.
For normal API authorization, validate the access token and enforce the required permission from its space-separated scope claim. groups and resource_roles are not ordinary access-token claims. Only use role or group checks when a trusted UserInfo or server-side session flow supplies those claims.
To migrate a trusted UserInfo or session role consumer:
- Remove
access_rolesfrom the requested OIDC scopes. It is not a separate request scope. - Request
profile. - Read
resource_rolesfrom the trusted UserInfo or server-side session claims. - Select roles using the resource server identifier as the object key.
For example, replace a flat claim check such as:
with a resource-scoped check:
Code should read resource_roles["https://api.example.com"] and test that array for reader. This preserves the resource server boundary and avoids collisions between roles with the same name.