Virtual Roles in EPiServer

Sample Alloy website comes preconfigured with several groups and virtual roles. However, in many real-world implementations having only WebEditors and WebAdmins groups is not sufficient.

So what's the difference between CmsEditors and WebEditors?

EPiServer can be configured to use any .NET role provider. If your EPiServer website uses EPi_AspNetIdentityUserProvider, it is very likely that roles (WebEditors) and role membership data (user A is a member of WebEditors group) will be stored in a database.

CmsEditors, on the other hand, is a virtual role. Virtual roles are defined in the code (not in a database like WebEditors). Moreover, role membership criteria are determined at runtime and can vary for each request.

How do I create my own virtual roles?

Let's say we want to create a virtual role for site visitors that are browsing the website using Google Chrome.

We could define a virtual role like this:

namespace Alloy
{
    public class UserAgentRole : VirtualRoleProviderBase
    {
        public string Agent { get; set; }

        public override bool IsInVirtualRole(IPrincipal principal, object context)
        {
            if (HttpContext.Current == null ||
                string.IsNullOrWhiteSpace(HttpContext.Current.Request.UserAgent))
            {
                return false;
            }

            return HttpContext.Current.Request.UserAgent.ToLowerInvariant()
                              .Contains(Agent);
        }

        public override void Initialize(string name, NameValueCollection config)
        {
            base.Initialize(name, config);

            string agent = config["agent"];
            if (string.IsNullOrWhiteSpace(agent))
            {
                throw new ArgumentException($"The 'agent' value for virtual role '{name}' is not defined.");
            }

            Agent = agent.Trim().ToLowerInvariant();
        }
    }
}

And register it in the web.config file like this:

<add name="ChromeUsers" type="Alloy.UserAgentRole, Alloy" agent="chrome" />

How do I use the virtual role for managing the access rights?

1. Go to admin mode, Select Access Rights and press the Add Users / Groups button.

Add groups in episerver cms

2. Change the search type to Groups and press the Search button.

searching groups in episerver cms

The list should contain all virtual roles that are defined in the code as well as roles that are available in role providers.

3. Select ChromeUsers group and press OK.

selecting groups in episerver cms

4. Select Read, Create, Change, Delete and Publish permissions and save changes.

setting access rights in episerver cms

How do I give permissions to users?

This is a very confusing part for many.

If you take a closer look at the web.config file, you may find something like this:

<location path="EPiServer">
  ...
  <system.web>
    <authorization>
      <allow roles="WebEditors, WebAdmins, Administrators" />
      <deny users="*" />
    </authorization>
  </system.web>
  ...
</location>

This tells the ASP.NET that only users that are members of either WebEditors, WebAdmins or Administrators group will have permission to access the edit mode.

It doesn't necessary mean that those users have permission to create, publish or delete pages just because the group name has “Editors” or “Administrators” in it. Setting access rights for pages is done in the admin mode, not web.config file.

One of the problems that many users are facing is that they cannot access the edit mode, they get the login screen over and over again but no error message saying that username or password are incorrect. If that happens to you, it means that your credentials are ok, but you are not a member of one of the groups specified in the allowed roles list.

So, to create a user, go to admin mode / Create user, enter all the information you need and make sure that user is a member of WebEditors group. It is very important not to choose the ChromeUsers group since that will override the logic inside the IsInVirtualRole method of UserAgentRole class!

creating users in episerver cms

Please note that in standard Alloy implementation WebEditors don’t have page editing permission. If that’s not the case with your EPiServer implementation, then you’ll have to create a new group in admin mode and update the allowed roles list in web.config file.

Testing

If you now log into the edit mode as a test user using Google Chrome, you should be allowed to edit pages:

accessing episerver edit mode using google chrome

However, if you log in using Internet Explorer, you'll have a read-only permission.

accessing episerver edit mode using internet explorer

Please note that user agent is not very reliable. It doesn't take much effort to change the user agent string. In addition, some browsers like MS Edge have “Chrome” as a part of the user agent string. That being said, UserAgentRole is not something you should use in real-world implementations, but it's good enough to demonstrate the possibilities of virtual roles.

Performance considerations

Virtual roles is a very powerful concept, but it comes with a high price, too. As mentioned at the beginning of this article, role membership criteria are determined at runtime and can vary for each request. While doing some testing with standard Alloy installation, I noticed that the code inside IsInVirtualRole method was executed 3 times when I was in the view mode, while the same code was executed 90 times when I was in the edit mode!

Virtual Roles are very powerful, but they should not be misused.

comments powered by Disqus