Limit Access to Documents for Site Visitors
Important note when using the walkthroughs
When the walkthroughs refer to some yaml configuration, in general, it is meant that you import this yaml into a locally running repository via the Console with auto-export enabled. If however you copy some yaml blob directly into your idea without auto-export, you have to uncomment the following lines if present in the yaml:
#.meta:category: system #.meta:add-new-system-values: true
The reason for this is that the auto-export for some properties knows implicitly to add this meta info, however the yaml import in the Console does not support .meta lines. Thus, you have two options when following the walkthroughs:
- Copy the yaml snippet as-is into the Console with auto-export running
- Copy the yaml snippet to your idea while uncommenting the commented meta info
Introduction
Goal
Limit access to documents to certain user groups by configuring authorization at document level.
Background
Bloomreach Experience Manager's delivery tier supports authorization at mount and sitemap item levels, as well as at individual document level using security domains.
This page provides a worked out example of an implementation project with authorization at document level.
Example
This example is based on a standard implementation project created from the Maven archetype, with the Blog feature added.
The requirements this example implements are defined as follows:
- Users can be a customer or staff member.
- Some Blog documents can only be accessed by visitor allowed to read staff or customer labeled blogs.
- Blog Documents with access level customer can only be accessed by customers and staff members.
- Blog Documents with access level staff can only be accessed by staff members.
The approach to implement the requirements is:
- Use the Selections feature to define a list of access levels and make the access level selectable in a Blog document.
- Create roles and groups for customers and staff members.
- Configure separate security domains for documents with customer access level, staff access level, and no access level defined.
- Configure the delivery tier to use the session of the logged-in user for authorization at document level (mind you, using a specialized session pool for this instead is better, see https://developers.bloomreach.com/blog/2017/custom-session-pools---a-case-study.html).
Prepare the Project
Create a project using the Bloomreach Experience Manager Maven archetype.
In Essentials, add the Blog feature to the project.
Rebuild and restart the project.
In the Console, select the node /hst:myproject/hst:configurations/hst:default/hst:sitemap/login and change the property hst:scheme from https to http. This configures the login page in the website to use HTTP instead of HTTPS in your local development environment (don't do this in production environments!).
Add an Access Level Field to the Blog Document Type
You are going to use the Selections feature to define the different access levels in a value list and make the access level selectable in the Blog document type.
In the CMS, create a subfolder inside 'myproject' called 'value lists'. Inside it, create a new Value List document called 'access levels'.
Enter the following values:
Key | Label |
---|---|
customer | Customer |
staff | Staff |
Save the value list document.
In Essentials, choose Tools, then Selections.
On the Document Types tab, add a new selection field to the Blog document type that enables authors to select the access level for a document:
- Select the 'blogtype' document type.
- Enter the name 'access level'.
- Select the selection type 'multiple'.
- Select presentation 'checkboxes'.
- Select the value list 'access levels'.
- Click 'Add new selection field'.
Exclude read access for unauthorized visitor
The first step is to make sure that for anonymous visitors, the Blog documents marked with access-level = staff or access-level = customer are not readable, and create security domains for authenticated visitors that can read customer blog documents and for visitors that can read staff and customer blog documents. For the anonymous visitors we need to constrain the default live-documents domain. At /hippo:configuration/hippo:domains/live-documents/hippo-document add :
/exclude-staff-docs: jcr:primaryType: hipposys:facetrule hipposys:equals: false hipposys:facet: myproject:accesslevel hipposys:filter: true hipposys:type: String hipposys:value: staff
and
/exclude-customer-docs: jcr:primaryType: hipposys:facetrule hipposys:equals: false hipposys:facet: myproject:accesslevel hipposys:filter: true hipposys:type: String hipposys:value: customer
After the above addition the default HST liveuser is not allowed to read live documents any more that have
myproject:accesslevel = staff
or
myproject:accesslevel = customer
Note that hipposys:filter: true means that the constraint only applies if the property myproject:accesslevel is present!
Create security domain for staff and customer visitors
For the customer visitor domain, copy the /hippo:configuration/hippo:domains/live-documents to /hippo:configuration/hippo:domains/live-documents-customer, remove the /exclude-customer-docs node, and replace the readonly node with the following content:
/readonly: jcr:primaryType: hipposys:authrole hipposys:role: readonly hipposys:groups: #.meta:category: system #.meta:add-new-system-values: true type: string value: [customers]
For the staff visitor domain, copy the just created customer domain /hippo:configuration/hippo:domains/live-documents-customer to /hippo:configuration/hippo:domains/live-documents-staff, and remove the /exclude-staff-docs node, and replace the readonly node with the following content:
/readonly: jcr:primaryType: hipposys:authrole hipposys:role: readonly hipposys:groups: #.meta:category: system #.meta:add-new-system-values: true type: string value: [staff]
Now, we have a setup where the users in group customers can read blog documents with myproject:accesslevel = customer and users in group staff can read all blog documents and the default HST liveuser cannot read documents with myproject:accesslevel = customer | staff.
Create Customer and Staff Groups
Below /hippo:configuration/hippo:groups create two new groups
/customers: jcr:primaryType: hipposys:group hipposys:members: .meta:category: system .meta:add-new-system-values: true type: string value: [] hipposys:securityprovider: internal hipposys:userroles: [xm.webfiles.reader]
and
/staff: jcr:primaryType: hipposys:group hipposys:members: .meta:category: system .meta:add-new-system-values: true type: string value: [] hipposys:securityprovider: internal hipposys:userroles: [xm.webfiles.reader]
Create new users and assign them to the group customers or staff. Make sure that you do not add existing CMS users to these groups since the CMS users have too much read access for being a frontend user! The CMS users namely can also read preview versions of a document. If you want the CMS users to be able to login into the websites (as we do for the current website you are looking at), you need to make use of specialized session pools (session pool for staff-liveuser and for customer-liveuser where after authenticating the user, the rendering gets delegated to either the staff-liveruser or customer-liveuser. This is explained in https://developers.bloomreach.com/blog/2017/custom-session-pools---a-case-study.html and is in general a much better approach, though more complex to setup)
Protect Individual Documents
You are going to set access levels for individual Simple Content documents.
In the CMS, create some Simple Content documents inside the myproject/blogs folder and set their access level to customer, staff, or both.
Save and publish the documents.
Create a login
Setup a login functionality using JAAS login described at Delivery Tier Authentication Configuration.
Configure Authorization using Logged-In User's Session
You are going to define the delivery tier to use the session of the logged-in user to perform authorization.
In the Console, select the node /hst:myproject/hst:hosts/dev-localhost/localhost/hst:root and set the following two properties to true:
/hst:myproject/hst:hosts/dev-localhost/localhost/hst:root:
hst:sessionstateful: true
hst:subjectbasedsession: true
This configures the delivery tier to perform authorization using the session of the logged-in user instead of the standard liveuser. As mentioned above, this has a performance penalty and has the downside that the authenticated user cannot also be a CMS user since a CMS user has too much read access (and can for example read preview and live document variants). So you'll need to maintain special users for logging in into the site. A much better approach is the custom session pools feature, but is more complex to setup.