Breaking a security pattern: XPath constraints on System.User specialisations
Data in Mendix applications is secured through entity access. These XPath constraints are used to constrain read, write and delete actions on specific entities. However when it comes to specialisations of System.User Mendix implemented a different approach.
The pattern: Applying security to inheritance
When applying security to inheritance the Mendix Runtime will look to the lowest subclass (specialisation) of the object for access rules. Entity access constraints are not inherited from the generalisation. This means that XPath constraints specified on the generalization no longer apply in the context of the specialisation.
I’ve discussed this more extensively in a previous post: Applying security to inheritance.
The security pattern is to explicitly specify the security per entity and thus define the access rules on the specialisation.
Breaking it: Entity access on System.User specialisations
The System.User entity is the exception to this rule. Specialisations of System.User
(like Administration.Account
) cannot change the access (read, write, delete) with their entity access rules.
Mendix has built in access rules for User objects which are always applied, there is no way to overwrite or modify these rules through the specialisation.
Caution
The System.User entity has inbuilt access rules where access is given to its attributes based on manageable roles, this is not changed by access rules applied to the specialisation
Manageable roles
A user role can manage users with a number of other user roles1, this is called manageable roles. This means that end-users who have this user role, can create, view, edit and delete users with at most the manageable user roles2. Regardless of what the specialisations will specify in the access rules.
Example: an end-user with the role Manager is allowed to manage all other employee roles. All employee accounts are created as a specialisation Organization.Employee
. The access to this entity is constrained with an XPath constraint, which allows a Manager to only view Employees of the their own department. The Manager role can view and manage Employees through an overview page. The end-user would still see all Employee objects for the roles the end-user is allowed to manage, including those of other departments. Which might not be what is expected based on the defined entity access.
Mendix deviates from the established security pattern which could lead to unexpected behaviour and unintended data exposure. Always make sure to check if the defined manageable role(s) and entity access limit the access correctly.
How it works
The Manageable Roles and Access Rules on System.User specialisations tend to act as additive rules for visibility, which means if you apply both: the rules will be combined. The table below will enumerate possible combinations and their outcome (in the context of a System.User specialisation like Organization.Employee).
Manageable Role | Entity Access Specialisation | Object visibility | Specialisation attributes | System.User attributes | Notes |
---|---|---|---|---|---|
No | No access | - | - | - | Only access to own object You wouldn’t be able to use the specialisation object (Employee) in pages, because of the error: CE2729 No access to entity 'MyFirstModule.UserAccount' for user role 'X' (with role 'X' in module 'MyFirstModule') |
No | Full access | Visible (all) | Accessible (all) | Not accessible | Only specialisation attributes are accessible, none of the System.User |
No | Limited access (e.g. own department only) | Visible (only same department) | Accessible (only same department) | Not accessible | Only specialisation attributes are accessible for user objects of the same department, none of the System.User |
Yes | Limited access (e.g. own department only) | Visible (only manageable + same department) | Accessible (only same department) | Accessible (only manageable) | The specialisation attributes are only accessible for users of the same department, System.User attributes are accessible for the manageable users. This is the example scenario described previously |
Yes | Full access | Visible (all) | Accessible (all) | Accessible (only manageable) | Specialisation attributes are accessible, System.User attributes are accessible for the manageable users |
Summary
- System.User attributes accessibility is controlled by the User Management Properties (Manageable roles)3
- Specialisation attributes accessibility is controlled by Entity Access Rules
- Visibility of the object is a combination of both
Securing System.User specialisations
There are different ways in which you can set up user management in your application. This section will cover several aspects of securing System.User specialisations, taking into account that entity access on System.User specialisations won’t fully secure your app.
Firstly, there is an important difference between Users and Persons/Profiles. Try to keep these two concepts separated, things like FullName, Date of Birth, Job Title are typically properties of a person or profile but not of a User account. Keep person and (user) account separated; don’t create inheritance structures of System.User for these kind of entities and attributes (even if it feels simpler, and yes Mendix made it confusing), create an association instead. A user account is really what you use to sign in to a system, persons are managed somewhere else. Once that has been established, it is also a lot easier to determine who should manage User accounts!
Secondly, try to stick to the Mendix built in User Management properties whenever possible. User Management should be secured through the Manageable Roles setting in the App Security. Only build your own solution if you are certain it doesn’t fit within the standard platform capabilities.
Thirdly, define security principles and stick to them. A good example is the Principle of least privilege (PoLP): Only give the minimum level of access rights (privileges) that is necessary for that person or process to complete an assigned operation.
Guidelines
Not all apps will be able to fit into this perfectly, so here are a few tips and guidelines to keep your app secure:
- Manageable user roles should be set as strict as possible (PoLP) and avoid the possibility of privilege escalation where an end-user can obtain more privileges by assigning themselves a more privileged user role
- XPath constraints added on pages, data grids etc. are visibility constraints, not security constraints, do not use this as a security measure
- Administrator user(s) like MxAdmin should only be used for technical app configuration (SSO and/or integrations), delegate management of business user accounts to a different role (e.g. BusinessAdministrator)
- Use SSO when possible (limit the usage of local accounts) or add 2FA
- Keep track of changes to users and their user roles
- Avoid stacking of multiple user roles
- Regularly review the user roles, their access and the mapping to the organization
Multi-tenant solutions
Multi-tenant applications where each tenants manages their own set of users require special attention. Tenant User roles should not be configured through the manageable roles in the App Security. A custom user management implementation is required, an example is available in the marketplace: Multi tenant administration. This is to prevent any tenant user from seeing other tenant users.
Users can still edit their own account (Password, Language, Time zone) even if end-user has no manageable roles ↩︎
Due to the at most condition, end-users can only manage users with multiple roles if the end-user has all required manageable roles. If a user has one or more roles that are not selected as manageable for the end-user, the end-user cannot manage the System.User attributes of this user. ↩︎
You would be able to access attributes of your own System.User object, but no specialisation attributes of your own object (see also footnote 1) ↩︎