Recently, I worked on a SharePoint project which used a Claims based web application. One of the web part was calling a custom web service hosted in ISAPI folder of SharePoint. The call was made via a server side proxy using C# code. And this particular design resulted in quite big challenge. While calling the web service from a web part using a service proxy, I noticed that user account being passed to the web service is NT Authority\IUSR.
On the other hand, if I created a site collection under Windows Authenticated web application and deploy the web parts in this site collection; the behaviour is different (and desired) i.e. the web parts communicate to the web service which is still deployed under Claims based web application. With this design, the identity in web service is same as that of logged in user.
Resolution:
The closest issue I found someone else had was Danny Hansen, atleast in terms of the error message. But unfortunaly, the resolution did not seem to help me in my issue.
After doing some more rounds of trial and errors with some reseach, I came to know about Claims to Windows Token Service. Basically, in claims mode the WindowsIdentity of the user does not exist because it is created as a IClaimsIdentity (that is, in .NET 3.5, an interface that inherits IIdentity). For this reason, developer must call a special .NET WCF service called C2WTS (claims to windows token service) that will return a WindowsIdentity that can be used for delegation. It is a .NET service that is configured in SharePoint and procedure to configure it is quite long and must be carefully followed, otherwise it will not work. Configuration step by step is available in http://support.microsoft.com/kb/2722087.
For the web service to work, below is the code I modified to implement what I describe above:
public static WindowsIdentity GetWindowsIdentityFromClaimsToken()
{
WindowsIdentity wi = null;
// Run this portion of code as application pool account, so that C2WTS service is called as this account
SPSecurity.RunWithElevatedPrivileges(delegate()
{
// Get the UPN value of the user from the UPN claim type
IClaimsIdentity identity = (ClaimsIdentity)Thread.CurrentPrincipal.Identity;
string upn = null;
foreach (Microsoft.IdentityModel.Claims.Claim claim in identity.Claims.Where(claim => StringComparer.Ordinal.Equals(ClaimTypes.Upn, claim.ClaimType)))
{
upn = claim.Value;
}
if (upn == null)
{
throw new Exception(string.Format("Cannot Impersonate {0} since he doesn't have a UPN in his claims", Thread.CurrentPrincipal.Identity.Name));
}
// Get a WindowsIdentity from the UPN of the user by calling C2WTS service
try
{
wi = S4UClient.UpnLogon(upn);
}
catch (System.Exception ex)
{
throw new Exception(string.Format("Impersonation failed. Message: {0}", ex.Message));
}
});
return wi;
}
using (WindowsImpersonationContext ctxt = Utility.GetWindowsIdentityFromClaimsToken().Impersonate())
{
//Call the web service here...
}
The function GetWindowsIdentityFromClaimsToken basically returns the windows token from Claims Token. To read more about C2WTS, here is a link to MSDN documentation:
Be First to Comment