mod-roles-keycloak
- 1 Overview
- 2 Functionality
- 3 Core models and entities
- 3.1 Role
- 3.2 Key terms
- 3.3 Role types
- 3.4 DEFAULT roles (system-provided)
- 3.5 REGULAR roles (tenant-defined)
- 3.6 User-Role
- 3.7 Policy
- 3.8 Capability
- 3.9 Capability Set
- 3.10 Role-Capability
- 3.11 Role-CapabilitySet
- 3.12 User-Capability
- 3.13 User-CapabilitySet
- 3.14 Loadable Role
- 3.15 Loadable Permission
Overview
mod-roles-keycloak is a Spring-based module responsible for the following functionality:
Role management
Policy management
Capability and capability set storage
Permissions mapping to capabilities and capability sets
Links management between roles and capability and capability sets
Links management between users and capability and capability sets
Keycloak role, policy management based on entities stored in
mod-roles-keycloakKeycloak permission management based on existing relations between users and roles to capability and capability sets
User folio-permissions for
_selfrequest
GitHub repository: https://github.com/folio-org/mod-roles-keycloak
API-Documentation: https://s3.amazonaws.com/foliodocs/api/mod-roles-keycloak/s/mod-roles-keycloak.html
Functionality
Role management
mod-roles-keycloak allows role management:
A user can view, create, edit, and delete roles
A user can assign and unassign roles to/from a user
Policy management
mod-roles-keycloak allows policy management:
A user can view, create, edit, and delete policies for types:
time,role,user
In current implementation, policies are created during the capability and capability set assignment to the role or user.
Policies created by users are not used in authorization processes.
A generated name for role policy would look like: Policy for role: {roleId}, for user: Policy for user: {userId}
Capability and capability sets
mod-roles-keycloak receives events with permission data from mgr-tenant-entitlements and transforms permission data into capabilities and capability sets:
Permission-Capability/CapabilitySet mapping algorithm
Reference roles (Loadable roles)
mod-roles-keycloak can store pre-defined roles as reference data and be populated through the Tenant Entitlement process.
Loadable role JSON file has the following format:
{
"roles": [
{
"name": "{{role name}}",
"description": "{{role description}}",
"permissions": [
// list with Folio permission name
]
}
]
}Reference data policies
mod-roles-keycloak can create a policy from reference data.
Policies JSON example:
{
"policies": [
{
"id": "15f45670-1edf-441e-a247-51f6c000faa3",
"name": "Business Hours",
"type": "TIME",
"source": "USER",
"timePolicy": {
"start": "2023-07-01T00:00:00",
"expires": "2033-07-01T00:00:00",
"logic": "POSITIVE",
"monthStart": "1",
"monthEnd": "12",
"hourStart": "8",
"hourEnd": "20"
}
}
]
}
Permission migration
mod-roles-keycloak provides an API to migrate existing user permissions from mod-permissions and assign them to newly created roles with unique names, based on SHA1 hash from all contained permissions to this role.
Algorithm is described at User permissions migration.
Core models and entities
Role
Eureka introduces Role-Based Access Control.
Roles are now the main part of FOLIO’s access model after the move to the Eureka platform. Under the old Okapi setup, a user got a long list of individual permissions. Since the Sunflower release, Eureka uses role-based access control.
A role groups many capabilities (single permissions) or capability sets (permission sets) and is then linked to one or more users. All role data lives in Keycloak; the FOLIO side talks to it through mod-roles-keycloak.
Key terms
Term | Short definition |
|---|---|
Capability / Permission | One atomic right, e.g. users.item.get. |
Capability Set / Permission Set | Named list of capabilities. |
Role | Container that holds capabilities or sets; never other roles. |
Loadable role | Role shipped as reference data or role managed by the system and auto-loaded by the platform. |
Role types
Type | Who creates it | Properties |
|---|---|---|
DEFAULT | System | Immutable, loadable, auto-updates when new capabilities appear. |
REGULAR | Tenant admins (or any user with role-create) | Fully editable, can be deleted. |
CONSORTIUM | Tenant admins (or any user with role-create) | Fully editable. Changes propagate automatically to all tenants. Can be deleted, and deletion will occur automatically across all tenants. |
DEFAULT roles (system-provided)
Immutable – name and membership cannot change through UI or Roles API.
Self-updating (Loadable Roles) –
mod-roles-keycloakkeeps each role in sync with its design: when new capabilities appear, it adds them automatically so the role always matches its intended list.Example: a DEFAULT role already contains a permission that is defined in the module descriptor of Module X. If Module X is not yet enabled for the tenant, that permission is missing from the system. Once the Module X is enabled for the tenant,
mod-roles-keycloakdetects the new capability or capability set and immediately inserts it, bringing the role to its final shape.
REGULAR roles (tenant-defined)
Created and managed by staff with the role-create capability.
Fully mutable: rename, add/remove capability sets, or delete.
Keep them broad (e.g. OA Admin, Acquisition Administrator) to avoid many near-duplicate roles.
Changes become active immediately; just refresh the page.
CONSORTIUM
Created and managed by staff with the role-create capability.
Fully mutable: rename, add/remove capability sets, or delete(changes are automatically applied in all tenants)
Changes propagate asynchronously to all tenants
The role ID for the same role can be different across tenants because Keycloak only supports autogenerated IDs
A role in Keycloak is a fundamental building block used for access control and authorization within the Keycloak identity and access management system. Roles define a set of permissions or capabilities that can be assigned to users or groups to regulate their access to resources and functionalities within an application or system. By assigning roles, administrators can manage user permissions in a scalable and organized manner, ensuring that users have the appropriate level of access required to perform their duties while maintaining security and compliance.
Property | Type | Description |
|---|---|---|
| UUID | A unique identifier for this role |
| String | A human-readable name/label for this role |
| String | A free form description of the role |
| String (enum) | Role type One of |
| metadata | System-generated metadata (createdBy, updatedBy, createdDate, updatedDate) |
User-Role
Describes a relation between user and role.
Property | Type | Description |
|---|---|---|
| UUID | A user identifier |
| UUID | A role identifier |
| metadata | System-generated metadata (createdBy, updatedBy, createdDate, updatedDate) |
Policy
A policy in Keycloak is a set of rules and conditions used to determine whether a user or group is authorized to access a particular resource or perform a specific action within an application or system. Policies are key to Keycloak's authorization services, enabling fine-grained access control by evaluating attributes, roles, and other contextual information to make dynamic access decisions. By defining policies, administrators can implement complex access control mechanisms beyond simple role-based access control (RBAC), incorporating attributes and environmental conditions into the authorization process.
Property | Type | Description |
|---|---|---|
| UUID | A unique identifier for this policy. System-generated if not provided. |
| String | A human-readable name/label for this policy. Required. |
| String | Free form description of the policy. Optional. |
| String (enum) | The type of policy. Required. One of |
| String | The type of policy. Required. One of |
| user_policy | An object containing the details of the user-based policy |
| time_policy | An object containing the details of the time-based policy |
| role_policy | An object containing the details of the role-based policy |
| metadata | System-generated metadata (createdBy, updatedBy, createdDate, updatedDate) |
Capability
A capability represents a specific functionality or access right within a system that allows users to perform certain actions or access particular resources. Capabilities are derived from permissions in the module descriptor, which define the rights required to execute a given functionality. By encapsulating permissions into capabilities, systems can manage and control user access more effectively, ensuring that only authorized users can perform sensitive operations or access restricted data.
Property | Type | Description |
|---|---|---|
| UUID | A unique identifier for this capability |
| String | A human-readable name/label for this capability. |
| String | Free-form description of the capability |
| String | The resource this capability is associated with |
| String (enum) | Еhe action this capability is associated with. |
| String (enum) | The type of capability. |
| String | Source folio permission name |
| String | The id of the application which defines the capability |
| String | The id of the module which defines the capability |
| Endpoint[] | List of associated endpoint with. |
| metadata | System-generated metadata |
Capabilities with type equal to Data usually have the following scopes: View, Edit, Create, Delete, Manage
The name for such capabilities is usually a noun: Fiscal Year, Instance Item, Instance Collection
Capabilities with type Procedural have action Execute
The name for such capabilities is usually more description and can be a verb: Orders-Storage Audit-Outbox Process, UI-Export-Manager Jobs Download-And-Resend
Capability Set
A CapabilitySet is a collection of related capabilities grouped to define a broader range of functionalities or access rights within a system. By uniting multiple capabilities into a single set, a CapabilitySet allows for more efficient and organized user permissions management, making assigning and controlling access based on roles, tasks, or specific use cases easier. This approach simplifies the process of granting users the necessary rights to perform various related actions without having to manage each capability individually.
CapabitySet can only include other capabilities and does not support hierarchical assignment.
During the processing of incoming permissions all permission sets with subpermissions are mapped to the capabilitySets with flattened list of found capabilities by permission names.
An additional table permissions stores source information about permissions (which can duplicates part of data from mod-permissions)
For UI permissions sets, to store a source permission name → an additional technical capability is created to store source permission name and other permissions are flattened and attached to the new CapabilitySet
Property | Type | Description |
|---|---|---|
| UUID | A unique identifier for this capability |
| String | A human-readable name/label for this capability. |
| String | Free-form description of the capability |
| String | The resource this capability is associated with |
| String (enum) | Еhe action this capability is associated with. |
| String (enum) | The type of capability. |
| String | Source folio permission name |
| String | The id of the application which defines the capability |
| String | The id of the module which defines the capability |
| UUID[] | List with assigned capability ids. |
| metadata | System-generated metadata |
Role-Capability
Property | Type | Description |
|---|---|---|
| UUID | Role identifier |
| UUID | Capability identifier |
| metadata | System-generated metadata |
Relation between capability and role.
Creating a relation between capability and role will result in the following permissions will be created in Keycloak:
# mod-roles-keycloak
Capability("{{capabilityId}}", "foo.item.view", "/foo/item/{id}")
Role("{{roleId}}", "Foo Role")
create RoleCapability("{{roleId}}", "{{capabilityId}}")
# keycloak (client = {{tenant}}-application)
GET access for role '{{roleId}}' to '/foo/item/{id}'Each permission is stored in an atomic way and each permission unites 3 entities: