Implementing page permission checks

Permissions and authentication requirements can be configured individually for specific pages or sections on Xperience websites. This page describes scenarios where developers need to consider page permissions when implementing the live site application. For general information about page permissions, see Page-level permissions (ACLs).

The implementation requirements for page-level permissions primarily depend on the routing scheme of your website:

  • Content tree-based routing – page permissions are automatically checked when displaying pages on the live site, based on the Check page-level permissions setting. However, you may need to implement filtering based on permissions or authentication requirements when loading page data.
  • Custom routing using URL patterns – for page permissions to have an effect on your website, developers need to use the appropriate API when loading and displaying pages in the site’s code.

Filtering pages based on permissions

You can control which users and roles can view pages on the live site by configuring Read permissions for pages and extending the DocumentQuery call that retrieves page content with the CheckPermissions method. The method ensures the retrieved collection only contains pages for which the current user has the Read permission.




var articles = new DocumentQuery<Article>()
                    .OnSite("MySite")
                    .Culture("en-us")
                    .Path("/Articles", PathTypeEnum.Children)
                    .CheckPermissions());


The retrieved pages are now filtered based on Read permissions, so only the specified users can view the content on the live site.

Note: The CheckPermissions method does NOT filter pages based on their authentication requirements (Requires authentication flag).

Checking authentication and authorization

The Xperience API allows developers to evaluate the authentication and authorization requirements of individual pages. You can access the security configuration for specific pages through instances of the IPageSecurity interface, which provides the following members:

  • UserMeetsAuthenticationRequirements – method that returns true if the page does not require authentication (is publicly available) or if the current user is already authenticated.
  • IsUserAuthorizedToAccess– method that returns true if the current user is authorized to access the secured page based on its permissions and the site’s configuration (the Check page-level permissionssetting from the Security & Membership category).
  • IsSecuredbool property that directly returns the status of the page’s Requires authentication flag (regardless of the site’s other configuration and settings).

To get the IPageSecurity instance for a page, use one of the following approaches (depending on your scenario and context):

  • Call the Retrieve method of the IPageSecurityRetriever service, with the page’s TreeNode object as the parameter.
  • Access the Security property of an IPageDataContext instance. The data context for the current page can be retrieved using the IPageDataContextRetriever service (requires manual initialization of the page data context for pages handled by custom routes based on page type URL patterns).
  • Access the Security property of an IPageViewModel instance – available as the model in the views of pages handled by basic content tree-based routing.

Examples

When displaying pages using a custom controller, you can call the IPageSecurity API to evaluate the page authentication and authorization requirements configured in Xperience, and return a suitable response.




using System.Net;
using System.Web.Mvc;

using Kentico.Content.Web.Mvc;

...

private readonly IPageDataContextRetriever dataContextRetriever;

public PageController(IPageDataContextRetriever dataContextRetriever)
{
    // Initializes an instance of the IPageDataContextRetriever service
    this.dataContextRetriever = dataContextRetriever;
}

public ActionResult Index()
{ 
    // Gets the page data context for the current page
    // Requires manual initialization of the page data context if using custom routes and page type URL patterns
    IPageDataContext<TreeNode> dataContext = dataContextRetriever.Retrieve<TreeNode>();

    // First evaluates whether the page requires the user to sign-in
    // If required, redirects to the site's sign-in page
    if (!dataContext.Security.UserMeetsAuthenticationRequirements())
    {       
        return new HttpUnauthorizedResult();
    }

    // Evaluates whether the current user's permissions are sufficient to access the page
    // If not authorized, returns an HTTP status 403 response
    if (!dataContext.Security.IsUserAuthorizedToAccess())
    {
        return new HttpStatusCodeResult(HttpStatusCode.Forbidden);
    }

    // Displays the page when the current user meets all authentication and authorization requirements
    return View();
}


The IPageSecurity API can also be useful when filtering retrieved pages based on security requirements. For example, when loading navigation menu items, you may wish to filter out pages that require authentication for non-authenticated users.




using System.Collections.Generic;

using Kentico.Content.Web.Mvc;

...

// Instances of services used to load pages and their security configuration (e.g., obtained via dependency injection)
private readonly IPageRetriever pageRetriever;
private readonly IPageSecurityRetriever securityRetriever;

...

// Retrieves a collection of pages, filtering out pages that require authentication if the current user is not signed in
IEnumerable<TreeNode> pages = pageRetriever.Retrieve<TreeNode>(query => query
                                 .Where(page => User.Identity.IsAuthenticated || !securityRetriever.Retrieve(page).IsSecured));