Back to Insights

Impersonation in SharePoint 2010 service applications

Recently I had a chance to help out on an interesting problem: content, including author information, had to be migrated from an external system to SharePoint 2010. One of the requirements was to post all content, specifically SharePoint 2010 social comments, under the identity of the user who was already provisioned to the site. In other words, we needed to impersonate the user who will be calling this command:

SocialCommentManager socialCommentManager = new SocialCommentManager(SPServiceContext.GetContext(HttpContext.Current));
socialCommentManager.AddComment(new Uri("http://habaneros.com"), "my comments");

However, "SocialCommentManager" uses "HttpContext" to get the identity of the current user, thus even if you run the code under elevated privileges, your comment will still be posted under the credentials of the current user.

Here is the solution that did the trick:

using (SPSite site = new SPSite("http://myhost")) 
  {
    using (SPWeb web = site.OpenWeb())
    {
      SPUser user = web.EnsureUser("myhost\\impersonated_user"); 
      web.AllowUnsafeUpdates = true;
      HttpRequest request = new HttpRequest("", "http://myhost", "");  
      HttpContext.Current = new HttpContext(request, new HttpResponse(new StringWriter(CultureInfo.CurrentCulture)));  
      HttpContext.Current.Items["HttpHandlerSPWeb"] = web;  
      WindowsIdentity identity= WindowsIdentity.GetCurrent();  
      typeof(WindowsIdentity).GetField("m_name", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(identity, user.LoginName);
      HttpContext.Current.User = new GenericPrincipal(identity, new string[0]);
      SocialCommentManager socialCommentManager = new SocialCommentManager(SPServiceContext.GetContext(HttpContext.Current));
      socialCommentManager.AddComment(new Uri("http://habaneros.com"), "my comments");
      web.AllowUnsafeUpdates = false;
    } 
  }

The basic idea is to create a new "HttpContext" and preserve many of the existing parameters except user identity, which we first "ensure: EnsureUser". Then build the user context out of the impersonated windows identity: "new GenericPrincipal(identity, new string[0])"

Good luck!

Share