Thursday, February 15, 2007

SharePoint, WebParts, Impersonation and Editing List Items

What the hell is Impersonation?
Impersonation is one of the most useful mechanisms in Windows security. It's also fragile and easy to misuse. Careful use of impersonation can lead to a secure, easy-to-administer application. Misuse can open gaping security holes. In fact Bob can be Sarah and Sarah can be Bob :-)

Impersonation is still useful in some cases. This story is about WSS 2.0/Microsoft Sharepoint Portal Server 2003, but is still interesting for other applications in .NET.

Suppose ..
You have to create a webpart which can give users read permissions to certain files or folders.
You want to store extra information in a custom list with custom properties (from/until/user's full name).

The SharePoint List, which is the data store, must be synchronized through the webpart. Attention, the user may not modify the list by himself. So in this case, the list is read-only for a certain group of people and the webpart is our user interface, which can modify the list.

Solution
To be sure that the current user can only view the list, we will deny the edit list items' permission and only give him the read-only permission on the list.
Now we have a problem ... How can we write data programmatically to the custom List if you haven't the 'edit list items' permission? Of course, "Bob will we Sarah" ... impersonation !

Impersonation
The webpart is running as the current user called Bob. Suppose that 'Sarah' is a 'background user' which has the permission to edit list items. Bob hasn't the permission so ... He transforms into 'Sarah'. Click here to download the Impersonator class which helps you by transforming Bob into Sarah.

// current user : Bob (read only list permission)

Impersonator imp = new Impersonator("domain", "Sarah", "password");
imp.Impersonate();

// current user : Sarah (edit list permission)
// => now you can create new list items into the custom list

imp.Undo();

// Do not forget to call Undo(). This will stop the impersonation, which transforms Sarah back into Bob.

Editing List Items and Security conflicts

Please write the code below after the Impersonate() call and before the Undo() call.
It seems to be very easy. It is logical ... but permissions are tricky ...


SPSite site = new SPSite("http://server");
site.AllowUnsafeUpdates = true; //resolves this problem: The security validation for this page is invalid

SPWeb web = site.Rootweb;
SPList list = web.Lists["My Custom List"];

SPListItem newItem = list.Items.Add();
newItem["from"] = DateTime.Now;
newItem["until"] = DateTime.Now.AddDays(10);

newItem.Update(); // you only need the permission to edit List Items.
list.Update(); //when updating the list, you need to have the permission to modify List settings
//in this case we don't need an list update, because Sarah has no sufficient rights.

Difference between SPListItem.Update() and SPList.Update()

If you are administrator or another person which can modify the List settings, you can call the SPList.Update() without any problems. SPList.Update() do not only update the data in the list, but also fields and settings. That's why you need some more rights.

If you can only edit List Items, you need to call the SPListItem.Update() method.

This is very logical, but so frustrating when receiving an E_ACCESSDENIED exception.


More Information on SharePoint Security and Impersonation
Click here to read Jay Nathan's article on 15seconds.

1 comment:

Oliver said...

Dear Kristof,

You have done a good job developing Your Impersonator-class.

I have downloaded the code and added it to a webpart I'm currently developing - in my environment Your class is very helpful.

But there is one small bug: if a call to Impersonate() fails (perhaps due to wrong crdentials), the following call to Undo() throws an exception.
I suggest this change to Undo():

if (null != this.impersonationContext)
{
this.impersonationContext.Undo();
}

Regards,
Oliver