Sunday, February 27, 2011

SPSecurity.RunWithElevatedPrivileges Access denied issue

SPRunWithElevatedPrivileges allows you to run your SharePoint code in the context of the App Pool identity account.

Look at the piece of code below:


function void ListItemUpdate(Guid guId)
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
SPSite site = SPContext.Current.Site;
SPWeb web = SPContext.Current.Web;
web.AllowUnsafeUpdates = true;

SPList list = web.Lists["Products"];
SPListItem item = list.Items[guId];
item["ProductName"] = "Apple iPhone 4";
item["ProductPrice"] = "199";

item.Update();

web.AllowUnsafeUpdates = false;
});
}

So when a user with Read access tries to execute the above code, he gets an Access denied error, even after the code having the RunWithElevated Privileges set.

Lets examine, look at the code highlighted in yellow above. SPContext.Current.Site and SPContext.Current.Web runs the List Item update code in the context of the currently logged in user and not in the context of the App Pool identity.

Solution: Solution is to re-open new SPSite and SPWeb objects within the SPSecurity delegate block, lets rewrite the above code and fix the issue:

function void ListItemUpdate(Guid guId)
{
Guid siteId = SPContext.Current.Site.Id;
Guid webId = SPContext.Current.Web.Id;

SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite(siteId))
{
using (SPWeb web = site.OpenWeb(webId))
{
web.AllowUnsafeUpdates = true;

SPList list = web.Lists["Products"];
SPListItem item = list.Items[guId];
item["ProductName"] = "Apple iPhone 4";
item["ProductPrice"] = "199";
item.Update();

web.AllowUnsafeUpdates = false;
}
}
});
}

Running this piece of code fixes the Access denied issue and allows the code to run under AppPool identity.