Access Control / Authorization
- Access Control / Authorization
- Resource-based ACLs
- Principal-based ACLs
- Repository Configuration
JCR 2.0 specifies Access Control Management in section 16. The JCR API package is javax.jcr.security. It covers the authorization part, ie. what a certain user is allowed to do with the repository, but not UserManagement, which is provided by Jackrabbit as an implementation-specific feature.
Permissions / Privileges
These permissions, called "privileges", are defined by the JCR 2.0 specification. This is basically the set of read, create, modify and delete operations that can be done on nodes and properties via the JCR API. A repository can also define custom privileges.
jcr:readThe privilege to retrieve a node and get its properties and their values.
jcr:modifyPropertiesThe privilege to create, remove and modify the values of the properties of a node.
jcr:addChildNodesThe privilege to create child nodes of a node.
jcr:removeNodeThe privilege to remove a node.
jcr:removeChildNodesThe privilege to remove child nodes of a node.
jcr:writeAn aggregate privilege that contains:
jcr:allAn aggregate privilege that contains all available permissions, including
jcr:writeand the advanced permssions.
For advanced privileges, see section 16.2.3 of the JCR 2.0 specification.
The JCR 2.0 specification is modeled with resource-based access control lists in mind. That means that a resource = node is associated with a list of allow/deny entries for certain principals (users or groups), which naturally maps to store them along the JCR node. A core concept of resource-based ACLs is that they inherit the ACLs from the parent node, thus for each node, all the ACLs of its ancestor come into play as well.
Resource-based ACLs are the default access control mechanism in Jackrabbit 2.x.
- fully supported by the JCR API / specification
- very widely available ACL model (eg. file systems)
- simple resource inheritance
- default mechanism in Jackrabbit, no configuration needed
- cannot assign ACLs to non-existent nodes
- cumbersome when many users need un-groupable ACLs on a few resources (e.g. "subscriptions"), lots of ACL entries per resource
- permissions are stored right inside the content (can be cumbersome for backups, etc.)
How Resource-based ACLs are stored
Resource-based ACLs are stored per resource/node in a special child node
rep:policy. This one will have a list of
rep:GrantACE child nodes (usually named
allow0,...) for grant access control entries and
rep:DenyACE child nodes (usually named
deny0,...) for deny access control entries.
Each ACE node has a
rep:principalName STRING property pointing to the user or group this ACE belongs to, and a
rep:privileges NAME multi-value property, containing all the privileges of this ACE.
Note that you can read/browse these nodes using the JCR API, but cannot modify them. This must always happen through the JCR access control API.
API for setting resource-based ACLs
Note that there is a utility AccessControlUtils in jackrabbit-jcr-commons that simplifies the JCR API calls for ACLs a bit.
This is an example granting all rights to everyone, using the plain JCR API:
(for links and more code, see below)
Difference between getPolicies() and getApplicablePolicies()
AccessControlManager.getApplicablePolicies(path) returns an iterator over all applicable policies that you can potentially define for that node. This depends on what the implementation provides. Jackrabbit only supports one policy, the
AccessControlList. If this is already applied to that node (in case the node is not new) you get an empty iterator.
A more correct way (than the code sample above) would check if any of the policies returned by the iterator is an
AccessControlList and use that one. If you cannot find one for a new node, then that policy is not supported by that specific JCR implementation.
AccessControlManager.getPolicies(path) only returns the policies that are already applied (i.e. persisted and active) on that node. In case of a new node, this should be empty.
A different approach for specifying and storing ACLs is to assign certain principals (users or groups) a list of nodes that they are allowed or denied to work on. The nodes will be referenced by paths, and might even include wildcards.
To work with principal-based ACLs, a Jackrabbit-propietary extension to the ACL management API is required.
- permissions can be assigned to non-existent nodes
- permissions are stored separately from the content (good for content replication, backup etc.)
- good for having many users with un-groupable ACLs (e.g. "subscriptions"); resources don't get filled up with ACL entries
- additional Jackrabbit API has to be used for setting ACLs
- modeling resource inheritance requires more ACLs than resource-based
How Principal-based ACLs are stored
An access control list (
rep:ACL) is stored for each user and group (this is transparent, currently it's mirroring the users's home path at
/rep:accesscontrol/<principal-path>/rep:policy/). This consists of entries (
rep:ACE), which are either allow (
rep:GrantACE) or deny (
rep:ACE nodetype (used by both resource- and principal-based ACLs) defines the following two properties for principal-based usage. These exact same names need to be used as restrictions when using the Jackrabbit API (JackrabbitAccessControlList.addEntry()):
rep:nodePathdefines the (base) path of a subtree the ACL applies to (mandatory, PATH property)
rep:globdefines a glob pattern to restrict the subtree, both child nodes & properties (only a path matching is done) (optional, STRING property)
For the glob pattern, see http://jackrabbit.apache.org/api/2.2/org/apache/jackrabbit/core/security/authorization/GlobPattern.html (NodePath is the
rep:nodePath and restriction is the
API for setting principal-based ACLs
This uses the Jackrabbit (security) API extending the base JCR (security) API. Please note that this is example code and might need to be adapted
Classes used are:
To use a different ACL mechanism, a different AccessControlProvider must be configured. This is a per-workspace config, and must be set in the
workspace.xml of each workspace, or the
<Workspace/> element of the
repository.xml for to-be-created workspaces.
The following are built-in jackrabbit-core:
- Resource-based (default):
- Combined, resource+principal-based:
- AccessControlProvider as an interface to extend for custom acl
- general security config