Use permissions for search

You can configure Sitecore content search to only retrieve and show 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 also when you 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.

Configure permission-enabled search

The content search configuration has a computed field called _readaccess. For the Solr search provider, for example, 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 if false, both things are also false and permissions are not used at all for search 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 that Sitecore provides check changes to the security field when you use permissions-enabled search.

Performance considerations

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

We recommend that you complete the security configuration before you turn 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.

Use permissions when you search from the API

There are a number of helper methods you can use to build search queries that take permissions into account. The helper methods are in the Sitecore.ContentSearch.Security.QueryableExtensions class:

/// <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

You use the helper methods by implementing the IReadAccessSearchResult interface. Note that the scenario for using the helper methods is that you use 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:

/// <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 they support using the Sitecore.ContentSearch.Security.QueryableExtensionsclass.

The SearchSecurityOptions property

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

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:

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

and

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