Why does RunwithElevatedPriviliges not work in Event Handlers?
In SharePoint one of the most used methods is - "RunWithElevatedPriviliges". The common understanding of this method is that - Wrap this delegate around any method you want to run under the context of the app pool user's identity and hence with full permission.
But there are some subtle details which are required to properly use this method. Without knowing the details I guess we end up abusing the "RunWithElevatedPriviliges" method rather than using the method.
Lets go into the detail of how this method actually works. This method internally uses the age old, trusted way of impersonation - WindowsIdentity.Impersonate(). The "RunWithElevatedPriviliges" method was introduced in MOSS 2007 to make impersonation use easy. Now lets understand the intricate requirements for this method to be used properly:-
1. Always use new objects which are within the context of the call. Do not use any object which is outside the scope of the context. In other words, I mean that never use objects from SPContext rather create them using GUID's or other ways within the method call.
E:g. You can get the SPSite or SPWeb object's reference by getting it from SPContext. But for the method - "RunWithElevatedPriviliges" try using the object's created inside the delegate call. Use the objects as shown below (Check The bold text below):-
SPWeb webInUserContext = SPContext.Current.Web;
SPSite SiteInUserContext = SPContext.Current.Site;
Guid webGuid = webInUserContext.ID;
Guid siteGuid = SiteInUserContext.ID;SPSecurity.RunWithElevatedPrivileges(delegate()
{
// get the site in impersonated context
using (SPSite site = new SPSite(siteGuid)){
// get the web in the impersonated context
SPWeb web = site.OpenWeb(webGuid);
// Do your work hereweb.Dispose();
}});
The main reason for doing so is to ensure that all the objects are in the context of the App Pool's identity. This is extremely important to ensure the above point. (And I know that there is very little documentation on this point)
Now lets come to the main point - "RunWithElevatedPriviliges" - With Event Handlers. Normally we make use of the ItemEventProperties object to get the SPSite/SpWeb object. And even if we try to create new objects within the "RunWithElevatedPriviliges" method, we would not be able to get the context of the App Pool identity.
Just Remember one thing:- You can't use "RunWithElevatedPriviliges" with event handlers and the reason is the - ItemEventProperties object. And here is not the end of the problems - you can't even use Windows.Impersonate() as well.
The only workaround which would work here is - Explicit Impersonation. Create a SPUser object for the administrator, get SPToken of the user and then use this token to open the SPSite object using this token.
Sample code is below:-
SPUser user = web.AllUsers["kci\\sp_prodapppool"];
SPUserToken token = user.UserToken;
SPSite kciSite = new SPSite(site.Url, token);
SPWeb kciWeb = kciSite.OpenWeb();
Happy Coding :)
Comments
Anonymous
July 21, 2008
PingBack from http://blog.a-foton.ru/2008/07/why-does-runwithelevatedpriviliges-not-work-in-event-handlers/Anonymous
November 25, 2008
The comment has been removedAnonymous
November 25, 2008
Hi James, SPsite and SPweb objects can be obtained from either the SPWeb web = SPContext.Current.Web; SPSite site = SPContext.Current.Site; or the SPWeb web = properties.OpenWeb(); SPSite site = properties.OpenWeb().Site; I hope this helps. Regards, VarunAnonymous
November 26, 2008
Hi Varun, Thanks for your immediate feedback. Problem is that the access denied error is also thrown when invoking the OpenWeb() method on the properties object. It's almost as if you can't do anything really useful in an event handler if you're not an admin. Regards, JamesAnonymous
November 26, 2008
Hi James, Okay. So may I know which event handler are you writing the code in. Also, does SPContext work or even that doesn't work. Regards, VarunAnonymous
November 27, 2008
The comment has been removed