The JSR 170 specification does not define how permissions are managed or checked. So eXo JCR has implemented its own proprietary extension to manage and check permissions on nodes. In essence, this extension uses an Access Control List (ACL) policy model applied to eXo Organization model.
At the heart of eXo Access Control, is the notion of the identity concept. Access to JCR is made through sessions acquired against a repository. Sessions can be authenticated through the standard (but optional) repository login mechanism. Each session is associated with a principal. The principal is an authenticated user or group that may act on JCR data. The identity is a string identifying this group or user.'
There are 3 reserved identities that have special meanings in eXo JCR:
any: represent any authenticated session.
anonim: represent a principal for non-authenticated sessions. (No error, it's really "anonim").
system: represent a principal for system sessions, typically used for administrative purposes. System session has full access (all permissions) to all nodes; therefore be careful when working with system sessions.
Autocreation: By default, newly created nodes are neither exo:privilegeable nor exo:owneable but it is possible to configure the repository to auto-create exo:privilegeable or/and exo:owneable thanks to eXo's JCR interceptors extension (see JCR Extensions.
OR-based Privilege Inheritance: Note, that eXo's Access Control implementation supports a privilege inheritance that follows a strategy of either...or/ and has only an ALLOW privilege mechanism (there is no DENY feature). This means that a session is allowed to perform some operations on some nodes if its identity has an appropriate permission assigned to this node. Only if there is no exo:permission property assigned to the node itself, the permissions of the node's ancestors are used.
An access control list (ACL) is a list of permissions attached to an object. An ACL specifies which users, groups or system processes are granted access to JCR nodes, as well as what operations are allowed to be performed on given objects.
eXo JCR Access Control is based on two facets applied to nodes:
Privilegeable: Means that the user or group (also called principal) needs the appropriate privileges to access this node. The privileges are defined as (positive) permissions that are granted to users or groups.
Ownable: The node has an owner. The owner has always full access (all permissions) to the node, independent of the privilegeable facet.
A privilegeable node defines the permissions required for actions on this node. For this purpose, it contains an ACL.
At JCR level, this is implemented by an
<nodeType name="exo:privilegeable" isMixin="true" hasOrderableChildNodes="false" primaryItemName="">
<propertyDefinition name="exo:permissions" requiredType="Permission" autoCreated="true" mandatory="true"
onParentVersion="COPY" protected="true" multiple="true">
A privilegeable node can have multiple
The type of these values is the eXo JCR specific Permission type. The
Permission type contains a list of ACL.
The possible values are corresponding to JCR standard actions:
read: The node or its properties can be read.
remove: The node or its properties can be removed.
add_node: Child nodes can be added to this node.
set_property: The node's properties can be modified, added or removed.
An ownable node defines an owner identity. The owner has always full privileges. These privileges are independent of the
permissions set by exo:permissions. At JCR level, the ownership is
implemented by an
This mixin holds an owner property.
<nodeType name="exo:owneable" isMixin="true" hasOrderableChildNodes="false" primaryItemName="">
<propertyDefinition name="exo:owner" requiredType="String" autoCreated="true" mandatory="true" onParentVersion="COPY"
The exo:owner property value contains exactly one identity string value. There might be a long list of different permissions for different identities (users or groups). All permissions are always positive permissions; denials are not possible. When checking a permission of an action, it is therefore perfectly sufficient that the principal of a session belongs to the groups to which the concerned action is granted.
To grant or deny access to a node, eXo JCR applies a privilege resolving logic at node access time.
If a node is privilegeable, the node's ACL is used exclusively. If the ACL does not match the principal's identity, the principal has no access (except the owner of the node).
Non-privilegeable nodes inherit permissions from their parent node. If the parent node is not privilegeable either, the resolving logic looks further up the node hierarchy and stops with the first privilegeable ancestor of the current node. All nodes potentially inherit from the workspace root node.
The owner of a node is inherited in accordance with the same logic: If the node has no owner, the owner information of the closest owneable ancestor is inherited.
This inheritance is implemented by browsing up the node's hierarchy. At access time, if the node does not have owner or permissions, the system looks up into the node's ancestor hierarchy for the first ACL.
When no matching ACL is found in the ancestor hierarchy, the system may end up looking at the root node's ACL. As ACL is optional, even for the root node. If the root node has no ACL, the following rule is ultimately applied to resolve privileges:
any identity (any authenticated session) is granted all permissions.
In the following example, you see a node named "Politics" which contains two nodes named "Cats" and "Dogs".
These examples are exported from eXo DMS using the \"document view\" representation of JCR. Each value of a multi-value property is separated by a whitespace, each whitespace is escaped by x0020.
<Politics jcr:primaryType="nt:unstructured" jcr:mixinTypes="exo:owneable exo:datetime exo:privilegeable" exo:dateCreated="2009-10-08T18:02:43.687+02:00"
exo:permissions="any_x0020_read *:/platform/administrators_x0020_read *:/platform/administrators_x0020_add_node *:/platform/administrators_x0020_set_property *:/platform/administrators_x0020_remove">
exo:text="" exo:title="Cats_x0020_rule_x0020_the_x0020_world" />
exo:text="" exo:title="Dogs_x0020_are_x0020_friends" />
The "Politics" node is
exo:privilegeable. It has both an
exo:owner property and an
exo:permissions property. There is an
exo:owner="root" property so that the user root
is the owner. In the exo:permissions value, you can see the ACL that is a list
of access controls. In this example, the group *:/platform/administrators has all rights on
this node (remember that the "*" means any kind of membership).
any means that any users also have the read
As you see in the
jcr:mixinTypes property, the "Cats" node is
exo:owneable and there is an
exo:owner="marry" property so that
the user marry is the owner. The "Cats" node is not exo:privilegeable and has no exo:permissions. In this case, you can see the inheritance mechanism here is that the
"Cats" node has the same permissions as "Politics" node.
Finally, the "Dogs" node is also a child node of "Politics".
This node is not
inherits the owner of the "Politics" node (which is the user root).
Otherwise, "Dogs" is
exo:privilegeable and therefore, it has its own
exo:permissions. That means only the
users having a "manager" role in the group "/organization" and the
user "root" have the rights to access this node.
Here is an example showing the accessibility of two nodes (to show inheritance) for two sample users named manager and user:
The "+" symbol means that there is a child node "exo:owneable".
This session describes how permission is validated for different JCR actions.
read node: Check the read permission on a target node.
For example: Read /node1/subnode node, JCR will check the "read" permission exactly on "subnode".
read property: Check the read permission on a parent node.
For example: Read /node1/myprop - JCR will check the "read" permission on "node1".
add node: Check add_node on a parent node.
For example: Add /node1/subnode node, JCR will check the "add_node" permission on "node1".
set property: set_property on a parent node.
For example: Try to set /node1/myprop property, JCR will check the "set_property" permission on "node1".
remove node: Check the remove permission on a target node.
For example: Try to remove /node1/subnode node, JCR will check the "remove" permission on "subnode".
remove property: Check the remove permission on a parent node.
For example: Try to remove /node1/myprop property, JCR will check the "remove" permission on "node1".
add mixin: Check the "add_node" and "set_property" permission on a target node.
For example: Try to add mixin to /node1/subnode node, JCR will check the "add_node" and "set_property" permission on "subnode".
ExtendedNode interface which extends
interface provides additional methods for Access Control
|Assign a set of Permissions to a node.|
|Assign some Identities' Permission to a node.|
|Remove an Identity's Permission.|
|Remove the specified permission for a particular identity.|
|Clear the current ACL so it becomes default.|
|Return the current ACL.|
|Check Permission (|
identity" parameter is a user or a group name. The
permissions are the literal strings of the standard action permissions
(add_node, set_property, remove, and read).