In Focus

SPSecurity.RunWithElevatedPriviledges Vs SpUserToken Vs AllowUnsafeUpdates In SharePoint

In this article, you will learn about the concept of SPSecurity.RunWithElevatedPriviledges vs SpUserToken vs AllowUnsafeUpdates In SharePoint.

SPSecurity.RunWithElevatedPriviledges

 
What is this and why do we require it?
 
The delegate of this function allows a block of code to run with the privileges of an AppPool identity.
 
Basically, this runs with “System Account” and has site collection admin privileges of all site collections hosted by the AppPool.
 
Let's take a sample.
  1. SPSecurity.RunWithElevatedPrivileges(delegate()  
  2. {  
  3.     //New SPSite object.  
  4.      using (SPSite site = new SPSite(“site collection url”))  
  5.      {  
  6.            Using (SPWeb web -= site.OpenWeb())  
  7.     {  
  8.          //Do things by assuming the permission of the "system account".  
  9.     }  
  10.      }  
  11. });  
Here, we see that all operations are performed by creating a new SPSite object. Since current context variables created outside the subset will give “access denied” error, hence, we cannot run this code in the current context and instantiation of site collection URLs should always be done inside the block of code.
 
The "Microsoft.SharePoint.dll" runs with WIN32API for impersonation of the current thread. It does not create a new thread; instead, impersonates the current thread during elevation and reverts back to the original identity after execution. This can cause unpredictable issues in applications.
 
Why use it?
  • When we need to access a part of the code with identities of an AppPool account keeping in mind the security.
  • For making certain network calls.
  • Accessing data from different site collection within the same AppPool.
A few things to keep in mind
  • The AppPool must be a member of the Site Collection group with required permissions.
  • This does not work when the HTTP Context is null. For example, in Console Application or Timer Jobs. This is because it impersonates the current thread, which is not the case when we use it from an External (console or service). However, it works perfectly fine inside WSS pool. Hence, for these cases, we need to use SharePoint User Impersonation or we need to manually instruct our.exe to “RunAs” SharePoint AppPool Account if we must use with Console App.
  • RunWith Elevated privileges only provides full control access to current content DB of the Site collection. We can’t make changes to SPWebApp which is persisted to Configuration DB.
  • It may cause a security risk when used incorrectly since the current thread is elevated with AppPool Account.
  • This does not work with SandBox solutions where the code is executed inside UserService.

Alternative impersonation

 
An alternative for RunwithElevatedpriviledges is to use SPUserToken of the “System Account” with the current SPSite object. We can create a new instance of the SPSite object with the userToken or assign the user-token property of the SPSite object.
 
Let's take a look at the sample.
  1. //Creating a SPUsertoken object.  
  2. SPUserToken saUserToken = SPContext.Current.Site.SystemAccount.UserToken;  
  3. //passing to the constructor of the SPSite  
  4. SPSite spSite=new SPSite("siteURL",saUserToken);  
  5.   
  6. SPUserToken saUserToken = SPContext.Current.Site.SystemAccount.UserToken;  
  7. SPSite spSite=new SPSite("siteURL");  
  8. //assigning the UserToken property of SpSite.  
  9. spSite.UserToken= saUserToken;  
In the above example , we are using the current SPSite object for impersonation, hence restrictions of obscure bugs could be resolved.
We can use this code in the Console App and Sandbox solutions as well.
 
Why use it?
  • It is generally a best practice to use this to access SharePoint objects using the server side object model.
  • It should be used when we do not expect the user to have all permissions as in elevated privileges but the required permissions of a particular identity.
Things to keep in mind
  • The user must have read access to the site to run the code.
  • Anonymous users will fail to run the code

AllowUnsafeUpdates in SPWeb

 
This is a Boolean property of SPWeb object which can be set to True or False. Setting this property updates the database without any security validation. However, there are security risks involved including cross-site publishing.
 
We always need to set this property to “False” once our work is done.
 
Example of a sample is shown below.
  1. SPWeb web = SPContext.Current.Web;  
  2. web.AllowUnsafeUpdates = true;  
  3. // we can perform out list, listitem and web updates here.  
  4. web.AllowUnsafeUpdates = false;  
  5.   
  6. SPList list= web.Lists["list name"];  
  7. SPListItemCollection items= list.GetItems();  
  8. web.AllowUnsafeUpdates = true;  
  9. foreach (SPListItem item in items)  
  10. {  
  11.      item["Field"] = "new val";  
  12.      item.Update();  
  13. }  
  14. web.AllowUnsafeUpdates = false;  
Why use it?
 
As per an MSDN article, “AllowUnsafeUpdates is set to true when you are trying to update the database as a result of the GET request”. 
 
In SharePoint, there is a “FormDigest” Control which places a security validation on the page, when POST back to the server.SharePoint uses to check that the information to make changes to DB is coming from the page itself. However, when we fire any update from an external source, such as Powershell or code, there is no “FormDigest” information bundled and sent to SharePoint and hence it throws an exception. In order to overcome this situation, we change the Boolean value of “AllowUnsafeUpdates” property.
 
Eg: If you have a SharePoint List and you want to update something in SharePoint data which resides in Content DB, first you need to set it to false, do the modification, and set it back to true.
 
Things to keep in mind
  • The code will behave differently when called from a web application or a rich client. Because when httpcontext is null, there are zero chances of cross-site scripting, hence AllowUnsafeUpdates is set to true by default.
  • If the code is using a POST request, we should always call ValidateFormDigest() which will ensure the request is validated and would not have to worry about AllowUnsafeUpdates.