Lars Nielsen's Discoveries

March 20, 2011

Something to watch for with SPSecurity.RunWithElevatedPrivileges

Filed under: Development,SharePoint — Lars Nielsen @ 11:09 pm
Tags: ,

When you want to check whether the current user is a member of particular SharePoint group using the object model, you can use code like this below.  Note that I use SPWeb.SiteGroups not SPWeb.Groups because the group you are looking at might not have any permissions on the site.

private bool CheckIfApprover()
{
    SPWeb web = SPContext.Current.Web;
    if ( web.IsCurrentUserMemberOfGroup(web.SiteGroups["Approvers"].ID))
    {
         // Do something here
         return true;
    }
    return false;
}

However, what happens if the current user doesn’t have permissions to see the members of the “Approvers” group? This code will throw a security exception.  To avoid this, it’s best to wrap the code inside a call to SPSecurity.RunWithElevatedPrivileges. What this does is to cause the code to run with the identity of the application pool of the web application, which will have enough privilege to inspect all the groups.

So you end up with something like this:

private bool CheckIfApprover()
{
    SPWeb web = SPContext.Current.Web;
    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
        using (SPSite site = new SPSite(web.Site.ID))
        {
              using (SPWeb web = site.OpenWeb(web.ID))
              {
                  if (web.IsCurrentUserMemberOfGroup(web.SiteGroups["Approvers"].ID))
                 {
                       // Do something here
                       return true;
                 }
             }
        }
    });
    return false;
}

When using RunWithElevatedPrivileges you need to recreate the SPWeb object within a using statement as shown here, so that you have a more privileged reference to the SPWeb where the code can do its stuff with an elevated privilege level. So far, so good. But what happens when this code runs? If it gets to the return true statement it should return out of the method, right? No, because that statement is inside a delegate function. The return statement exits out of the delegate function, onto the next line which is return false. So the end result is that the CheckIfApprover() method returns false, not true, if the user is in the Approvers group. Inserting that SPSecurity.RunWithElevatedPrivileges segment has changed the way the method runs.

To get round this, you can declare a variable outside the delegate function, set it inside the function, and then return it when you come back out again, like this:

private bool CheckIfApprover()
{
    bool isApprover = false;
    SPWeb web = SPContext.Current.Web;
    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
        using (SPSite site = new SPSite(web.Site.ID))
        {
            using (SPWeb web = site.OpenWeb(web.ID))
            {
               if  (web.IsCurrentUserMemberOfGroup(web.SiteGroups["Approvers"].ID))
               {
                    isApprover = true;
               }
            }
        }
    });
    return isApprover;
}

That solves the problem with the control flow.  But there’s another trap lurking in the code above.  It lies in this expression:

web.IsCurrentUserMemberOfGroup(web.SiteGroups[“Approvers”].ID)

What will this do when you wrap it inside RunWithElevatedPrivileges?  It will check the account is in the approvers group, but it won’t check the account of the person working with the SharePoint site.  Instead, it will check the account under which the code is running, which is the identity of the application pool of the web application.  If you want to check that actual person’s account, and not that system-level account, you need to do things differently.  You can do this either by using the Groups property of SPUser or by testing if the current user’s account is in the Users property of the group – for details see the second response in this thread

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

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

Blog at WordPress.com.

%d bloggers like this: