Use permissions for search

Current version: 10.0

You can configure Sitecore content search to retrieve and show only items that the user executing the search has permission to read (permission-enabled search). The feature is available when you search through a Sitecore client and use the search API to build search queries in code.

By default, the feature is only enabled for Sitecore clients (in the Sitecore UI), and only for the sitecore_master_index index, but you can change this in the configuration.

The content search configuration has a computed field called _readaccess. For example, for the Solr search provider, this field is in the contentSearch/indexConfigurations/defaultSolrIndexConfiguration/documentOptions node in the Sitecore/ContentSearch/ Sitecore.ContentSearch.Solr.DefaultIndexConfiguration.config file.

The EnableReadAccessIndexing setting in the index configuration specifies two things:

  • Whether Sitecore stores the item:read access rights in the security field in the index.

  • Whether you can add additional clauses for the _readaccess field to the query.

If the value of the EnableReadAccessIndexing setting is true, both of these things are true. If the value is false, both things are false, and permissions are not used for searching in this index.

The feature is only enabled for the sitecore_master_index index by default.

To use permissions for searching the website:

  • Change the value of the enableReadAccessIndexing setting for the sitecore_web_index to true .

The indexing strategies check changes to the security field when you use permissions-enabled search.

Use permissions when you search from the API

Indexing strategies react to changes in the security field in content items, not to changes in the security domain configuration. Therefore, when you change the security domain, you must rebuild indexes that use permission-enabled search.

Note

We recommend completing the security configuration before you turn the permission-enabled search on. Adding new users to the system or assigning users to roles does not require index updates unless you assign access rights directly to users.

You can use several helper methods to build search queries that consider permissions. The helper methods are in the Sitecore.ContentSearch.Security.QueryableExtensions class:

RequestResponse
/// <summary>
/// Filters the specified source based on "item:read" access for user.
/// </summary>.
/// <typeparam name="T">The type of the source.</typeparam>
/// <param name="source">The source.</param>
/// <param name="user">The user.</param>
/// <returns>The results.</returns>
public static IQueryable<T> WhereUserCanRead<T>(this IQueryable<T> source, User user) where T : IreadAccessSearchResult

/// <summary>
/// Filters the specified source based on "item:read" access for role.
/// </summary>.
/// <typeparam name="T">The type of the source.</typeparam>
/// <param name="source">The source.</param>
/// <param name="role">The role.</param>
/// <returns>The results.</returns>
public static IQueryable<T> WhereRoleCanRead<T>(this IQueryable<T> source, Role role) where T : IReadAccessSearchResult

To use the helper methods to build queries that consider permissions:

  • Implementing the IReadAccessSearchResult interface.

Note

The scenario for using the helper methods is using a single method call. You cannot override the method parameter.

If you chain method calls (for example: query.WhereUserCanRead(userA).WhereUserCanRead(userB)), Sitecore filters the search results for both users.

The IReadAccessSearchResult interface

You use the IReadAccessSearchResult interface to specify that search query results must be filtered based on the value of the _readaccess field. It has a single property called ReadAccess. This property matches the _readaccess index field:

RequestResponse
/// <summary>
/// Interface for the search result that support <see cref="BuiltinFields.ReadAccess"/> index field.
/// </summary>
public interface IReadAccessSearchResult
{
    /// <summary>
    /// Gets or sets <see cref="BuiltinFields.ReadAccess"/> field.
    /// </summary>
    [IndexField(BuiltinFields.ReadAccess)]
    IEnumerable<string> ReadAccess { get; }
}

If you use a custom search result type and need the helper methods, you must implement the IReadAccessSearchResult interface in the custom type.

The built-in search result types, for example, SearchResultItem and UISearchResultItem, implement these interfaces and support using the Sitecore.ContentSearch.Security.QueryableExtensions class.

The SearchSecurityOptions property

When you use the API to build a search query, you use the SearchSecurityOptions property:

RequestResponse
public enum SearchSecurityOptions
{
    /// <summary>The default security options.</summary>
    Default = 0,

    /// <summary>
    /// Disables all security checks. 
    /// </summary>
    DisableSecurityCheck = 1 << 0,

    /// <summary>
    /// Runs a security check on all items.
    /// </summary>
    EnableSecurityCheck = 1 << 1,
}

When you set the value of the SearchSecurityOptions property to EnableSecurityCheck, Sitecore automatically applies the .WhereUserCanRead(Context.User) extension method to the query built by the client application or the API. This means that the following two code samples do the same:

RequestResponse
var index = ContentSearchManager.GetIndex("sitecore_master_index");
using (var context = index.CreateSearchContext(SearchSecurityOptions.EnableSecurityCheck))
{
    var query = context.GetQueryable<SearchResultItem>();
}

and

RequestResponse
var index = ContentSearchManager.GetIndex("sitecore_master_index");
using (var context = index.CreateSearchContext())
{
    var user = Context.User;
    var query = context.GetQueryable<SearchResultItem>().WhereUserCanRead(user);
}

Override search limitations

Permission-enabled search has some limitations for users with multiple roles.

Given a user with two roles, for example, Role1 and Role2, if an item is configured to deny read permissions for Role1 and one of its descendants allows reading for Role2, the descendants of the second item will not be returned in query results. This behavior respects the restrictions set on the first ancestor item.

The following content tree outline illustrates the limiting access rights configuration:

RequestResponse
sitecore
- content
-- Home {item:read access denied for descendants} for Role1
--- Level1
---- Level2
----- Level3 {item:read access allowed for descendants} for Role2
------ Item1
------ Item2
------ Item3

To return results listed under the Level3 item, you must override the restrictions set on ancestor items by configuring access rights for the role of interest on each descendant you want to retrieve in your search queries.

To override ancestor restrictions:

  1. Download and install the SC Hotfix 591876-1.zip package.

  2. Add the following setting to your Sitecore configuration:

    RequestResponse
    <!--  CONTENT SEARCH - INDEXING READACCESS WITH PRIORITY TO ENABLE FIX FOR 493002
    This setting specifies whether or not to indexing readaccess permission with proprity and search with prioriry.
    When enabled it will have extra priority to the readaccess permission when indexing e.g. 
    User > Entity > Descendents.
    Default value: false-->
    
    <setting name="ContentSearch.Enable-493002" value="false"/>
  3. Rebuild indexes.

  4. For the intended role (Role2 in this example), explicitly set access rights on the descendent items you want to be returned by enabling item:read access on each item:

    RequestResponse
    sitecore
    - content
    -- Home {item:read access denied for descendants} for Role1
    --- Level1
    ---- Level2
    ----- Level3 {item:read access allowed for descendants} for Role2
    ------ Item1 {item:read access allowed for the item} for Role2
    ------ Item2 {item:read access allowed for the item} for Role2
    ------ Item3 {item:read access allowed for the item} for Role2

Do you have some feedback for us?

If you have suggestions for improving this article,