How to limit read access for different site visitors? - BloomReach Experience - Open Source CMS

This article covers a Hippo CMS version 10. There's an updated version available that covers our most recent release.

13-05-2015

How to limit read access for different site visitors?

Suppose you have documents that are published, but should only be visible for certain (logged in) visitors. There are two way to accomplish this. For simplicity, assume anonymous users are  not allowed to see documents marked with property  myproject:access = internal. In that case you have the options:

  1. Anonymous visitors only cannot see the detail page for some document. They do however see the documents marked with  myproject:access = internal in search results, faceted navigation, links to such a document work, etc.
  2. Anonymous visitors are completely  blocked from seeing documents marked as  myproject:access = internal : This means links to such documents will be a 'notfound' link and search results or faceted navigation won't show these documents

Option 1 is trivial and won't be discussed here. In a nutshell, that solution can just be a hardcoded check whether the visitor is not an anonymous visitor (for example no logged in status in his  HttpSession). If the visitor is anonymous, and the page is a detail page for a document marked with  myproject:access = internal, then for example redirect to a login page, or show a 404, or show directly a login box, etc.

Option 2 is a more interesting solution, which is possible to  configure in a running production environment without restart. The rest of this page will describe which steps to take to achieve this.

The functional requirements

For the functional requirements, let's assume this www.onehippo.org website you are currently looking at. If you visit through the Documentation menu the Enterprise menu item in the left menu, you get a login box if you are not yet logged in.

When clicking on the Enterprise menu item, you get a log in box. After logging in, you have

  1. Access to the menu items and links below Enterprise menu item
  2. Read Access to documents that are marked with connect:access = 'partner'. (note the namespace prefix for the content of this website is connect). Note that thus after logging in, you will also find documents marked with connect:access = 'partner' in the search results and below the Library. Not logged in users will not get search results for documents containing connect:access = 'partner'.

Worked out example:

Note that due to HST Session pooling some of the changes below will only take effect after a couple of minutes (the JCR session first needs to expire)

Make the sitemap item belonging to Enterprise menu item protected

Assume you want visitors to have to log in when clicking Enterprise menu item, and that they should be in role partner. This is just plain HST Authentication and Authorization. This has not yet anything to do with read access for specific documents for logged in users, but only about authentication. Suppose you sitemap item is at hst:sitemap/library/enterprise. Make sure it contains something like:

+ hst:sitemap
    + library
        + enterprise
            - hst:authenticated = true
            - hst:roles = {partner}
            + **.html

The above configuration makes sure that

  1. All URLs below /library/enterprise need authentication
  2. That only users with role partner can log in.

Note that **.html inherits the authenticated and roles values from enterprise sitemap item.

How to configure a partner (say johndoe) can log in and has role 'partner'?

We assume you already created:

  1. A user  johndoe at  /hippo:configuration/hippo:users/johndoe.
  2. A group  partner at  /hippo:configuration/hippo:groups/partner that contains  hipposys:members = {johndoe}

For  johndoe to be able to log in, he needs to have the role  partner. Since the JAAS Login Module uses only one security domain for authentication which is by default the security domain everywhere (see  Authentication and Authorization), you need to add a  hipposys:authrole to the domain everywhere for group partner. You can thus for example add:

+ /hippo:configuration
     + hippo:domains
         + everywhere
             + partner [hipposys:authrole]
                 - hipposys:groups = {partner}
                 - hipposys:role = partner

This  hipposys:role is needed to make sure that  johndoe is in role partner. The role partner also needs to be created but does  not need any privileges as it is just a placeholder to identify  johndoe with role partner. Thus, also make sure you add a  hipposys:role without any properties as follows:

+ hippo:configuration
    + hippo:roles
        + partner
            - hipposys:role

Now you should be able to log in at  Enterprise menu item with user  johndoe.

Make sure a logged in partner can view documents that are not visible for anonymous visitors

The above is only about authenticating a user ( johndoe) in some role ( partner). However, after being authenticated, the page request for  johndoe is still rendered with the normal site liveuser. As already mentioned, we do not want a anonymous visitor (site  liveuser) to be able to view documents that are marked  connect:access = 'partner'. We thus need to do two more things:

  1. Make sure that an authenticated visitor in the partner role gets the site rendered with different  JCR session
  2. Make sure that the site  liveuser does not have read-access to documents marked  connect:access = 'partner'

Render the site with a JCR session belonging to the authenticated visitor

An  hst:mount can be configured so that the request needs to be processed with a  JCR session belonging to the authenticated visitor instead of the default liveuser. For anonymous visitors, the normal  liveuser is used, but for  johndoe, we want to render the page with a  JCR session that has more read-access. This can be achieved as follows. Assume the  hst:mount is located at

/hst:hst/hst:hosts/prod/org/onehippo/www/hst:root/10 

Then make sure that the  hst:mount  10 gets the properties:

+ 10
   - hst:subjectbasedsession = true
   - hst:sessionstateful = true (optional, performance only) 

Above, the  hst:subjectbasedsession = true makes sure that *if*  johndoe gets authenticated after logging in, the request is rendered with a  JCR session belonging to his credentials (See  Authentication and Authorization). Note that you might not be able to render the page yet as johndoe. This is described below as you still might need to account for the correct read access.

Limit Read Access for liveuser

In the use case described above,  johndoe as a member of  partner is allowed to view documents marked with property  connect:access = 'partner'. However, an anonymous user, which gets the page rendered by the HST liveuser, is not allowed to view those documents. We thus need to make sure that

  1. liveuser does not have read access for documents marked with property  connect:access = 'partner'
  2. johndoe does have read access to all live documents

Make sure johndoe has read access to all live documents

Since in this step, I assume the  liveuser has still access to all documents, you can copy

/hippo:configuration/hippo:domains/live-documents

To

/hippo:configuration/hippo:domains/partner-live-documents

and at

/hippo:configuration/hippo:domains/partner-live-documents/readonly

change  hipposys:groups = liveusers to

hipposys:groups = partner

Since  johndoe is a member of  /hippo:configuration/hippo:groups/partner, he should now be able to log in, and render the site with all documents visible (just like the  liveuser)

Make sure the liveuser does not have read access to documents marked with property  connect:access = 'partner'

At

/hippo:configuration/hippo:domains/live-documents/hippo-document

Make sure you  add a  hipposys:facetrule, for example called  exclude-partner-docs that contains:

<sv:node sv:name="exclude-partner-docs" xmlns:sv="http://www.jcp.org/jcr/sv/1.0">
  <sv:property sv:name="jcr:primaryType" sv:type="Name">
    <sv:value>hipposys:facetrule</sv:value>
  </sv:property>
  <sv:property sv:name="hipposys:equals" sv:type="Boolean">
    <sv:value>false</sv:value>
  </sv:property>
  <sv:property sv:name="hipposys:facet" sv:type="String">
    <sv:value>connect:access</sv:value>
  </sv:property>
  <!-- hipposys:filter = true means the filtering will only take place if the property
       'connect:access' exists -->
  <sv:property sv:name="hipposys:filter" sv:type="Boolean">
    <sv:value>true</sv:value>
  </sv:property>
  <sv:property sv:name="hipposys:type" sv:type="String">
    <sv:value>String</sv:value>
  </sv:property>
  <sv:property sv:name="hipposys:value" sv:type="String">
    <sv:value>partner</sv:value>
  </sv:property>
</sv:node>

The above extra  facetrule is to prevent  liveuser from reading documents marked as  connect:access = 'partner'.

Did you find this page helpful?
How could this documentation serve you better?
On this page
    Did you find this page helpful?
    How could this documentation serve you better?