Using declarative security in Sitecore

Forms data viewer is one example of a webform in Sitecore

The Forms data viewer is one example of a webform in Sitecore

Writing XAML applications for use in the Sitecore shell can be very tricky. And I admit that I often decide to use a webform instead. Especially if I need to write a minor application that does not use Sitecore data as such, but still needs to be a part of the Sitecore desktop.

One of the downsides of using an .aspx page in the shell is (besides the fact that the styling usually ends up being completely different from the Sitecore styling) is that the application can be called from outside of the Shell context. This is especially a problem if the application is used in public websites, as everyone, including my web site visitors, will be able to execute the page, if they know the URL.

One of the solutions is to implement my own Generic Identity and use declarative security in my webform. And it’s quite easy too. This code can be expanded, but I have kept it simple to demonstrate the principals. Implementing yout own security context requires a generic identity (a user) and a generic principal (a list of groups). The generic identity looks like this:

using System.Security.Permissions;
using System.Collections.Generic;
using System.Threading;
using System.Security.Principal;

/// <summary>
/// Class imlementing a generic identity
/// which equals one Sitecore user
/// </summary>
public class SitecoreIdentity : IIdentity
{
  private Sitecore.Security.Accounts.User _user;

  public SitecoreIdentity()
  {
    _user = Sitecore.Context.User; 
  }

  #region IIdentity Members

  public string AuthenticationType
  {
    // I cheat a little bit. Sitecore returns an empty AuthenticationType
    // so I use the domain name as authenticationtype instead
    get { return Sitecore.Context.Domain.Name; }
  }

  public bool IsAuthenticated
  {
    get { return _user.Identity.IsAuthenticated; }
  }

  public string Name
  {
    get { return _user.Name; }
  }

  #endregion
}

An identity is accompanied by a principal, which equals the roles that the identity (user) belongs to:

/// <summary>
/// Class implementing a generic principal
/// which equals the groups one sitecore user
/// belongs to
/// </summary>
public class SitecorePrincipal : IPrincipal
{
  private List<string> _roles = new List<string>();
  private IIdentity _identity;
  private Sitecore.Security.Accounts.User _user;

  public SitecorePrincipal(IIdentity identity)
  {
    _identity = identity;
    _user = Sitecore.Context.User; 
    // I add the administrator as a role to my principal so I can query it
    // when using declarative security
    if (Sitecore.Context.User.IsAdministrator)
      _roles.Add("Administrator");
    // Add all role names from the current user to my principal
    foreach (Sitecore.Security.Accounts.Role userRole in _user.Roles)
    {
      _roles.Add(userRole.Name);
    }
  }

  #region IPrincipal Members
  public IIdentity Identity { get { return _identity; } }
  public bool IsInRole(string role) { return _roles.Contains(role); }
  #endregion
}

I can now assign the current thread’s principal of the current webform to my own principal:

void Page_Load(object sender, System.EventArgs e)
{
  // Create new user
  SitecoreIdentity user = new SitecoreIdentity();
  // Assign the roles to that user
  SitecorePrincipal roles = new SitecorePrincipal(user);
  // Assign the roles to the current thread
  Thread.CurrentPrincipal = roles;
}

My webform is now runing under the security context of my Sitecore user, and I can now use declarative security to allow or disallow execution of code. The following function will only execute if a Sitecore user is authenticated:

[PrincipalPermission(SecurityAction.Demand, Authenticated=true)]
private void WriteText()
{
  Response.Write("Authentication: " + Thread.CurrentPrincipal.Identity.AuthenticationType);
  Response.Write("Is authenticated: " + Thread.CurrentPrincipal.Identity.IsAuthenticated);
  Response.Write("Name: " + Thread.CurrentPrincipal.Identity.Name);
}

It is the PrincipalPermission attribute that sets the security on my function. If the current Sitecore user is not logged in, .net will throw an exception.

Here is another example. This will allow access if the user is a Sitecore administrator, and block everyone else:

[PrincipalPermission(SecurityAction.Demand, Role="Administrator")]
private void WriteText()
{
  // ... your code here
}

About briancaos

Developer at Pentia A/S since 2003. Have developed Web Applications using Sitecore Since Sitecore 4.1.
This entry was posted in Sitecore 5, Sitecore 6 and tagged , , . Bookmark the permalink.

One Response to Using declarative security in Sitecore

  1. Pingback: XAML (SheerUI) dialog in Sitecore 6.3.x « Brian Pedersen’s Sitecore and .NET Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s