Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

I have tried to keep this as short as possible, dont hesitate if you want more details.

Im trying to get impersonation (of calling user) to work over a net.tcp WCF-Service in a Sharepoint 2010-solution Kerberos, Claims Based authentication, everything(Service-caller, Service-host, AD) runs on same (Virtual) Machine (for now) Win2008 R2 and IIS 7.5. Currently both caller and host are on same Sharepoint-webapp

I can call the service and I get the identity of the calling user with SPSecurityContext.GetWindowsIdentity(), but when I try to OpenWeb() I get AccessDenied (for all users but Administrator). I have failed to create a SPUserToken from the identity (I get error "Value cannot be null.Parameter name: claimValueOne"

Client-code:

using (SPSecurityContext.GetWindowsIdentity().Impersonate())
{
    var binding = new NetTcpBinding(SecurityMode.Transport);
    EndpointAddress epa = new EndpointAddress(new Uri(addressStr), 
                                new UpnEndpointIdentity  ("SP_WorkerProcess@MyDomain"));

    binding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
    binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;

    var channelFactory = new ChannelFactory<IRKDataService>(binding);

    channelFactory.Credentials.Windows.AllowNtlm = true;
    channelFactory.Credentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;

    channelFactory.ConfigureCredentials(SPServiceAuthenticationMode.Claims);
    IRKDataService channel = channelFactory.CreateChannelActingAsLoggedOnUser(epa);

    var departments = channel.GetDepartments();

}

Server-code

using (ServiceSecurityContext.Current.WindowsIdentity.Impersonate())
{
   using (SPSite site = new SPSite("http://mysite"))
   using (SPWeb web = site.RootWeb)
   {
      var user = web.CurrentUser;
   }
}

ServiceHost-code (inherits from ServiceHostFactory):

protected override ServiceHost CreateServiceHost(Type pServiceType, Uri[] pBaseAddresses)
{

    mBaseAddresses = pBaseAddresses;
    mServiceType = pServiceType;

    string strAddress = string.Format(BASE_ADDRESS_FORMAT_STRING, mServiceType.Name);

    ServiceHost host = new ServiceHost(pServiceType, new Uri(strAddress));
    host.Opening += (OnHost_Opening);


    //Add http-enabled behaviour
    ServiceMetadataBehavior behavior = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
    var wasExisting = (behavior != null);
    if (!wasExisting)
        behavior = new ServiceMetadataBehavior();

    behavior.HttpGetEnabled = false;//If you dont have HttpGetEnabled = false, youll get here many times without beeing able to add the service (as reference)...dont know wny
    if (!wasExisting)
        host.Description.Behaviors.Add(behavior);

    //Add include exception behaviour
    var debugBeh = host.Description.Behaviors.Find<ServiceDebugBehavior>();
    if (debugBeh == null)
        host.Description.Behaviors.Add(new ServiceDebugBehavior { IncludeExceptionDetailInFaults = true });
    else
        debugBeh.IncludeExceptionDetailInFaults = true;

    SPIisWebServiceApplication.ConfigureServiceHost(host, SPServiceAuthenticationMode.Claims);

    host.Authorization.ImpersonateCallerForAllOperations = true;
    host.Credentials.WindowsAuthentication.AllowAnonymousLogons = false;            
    return host;
}



protected void OnHost_Opening(object sender, EventArgs e)
{
    ServiceHost host = sender as ServiceHost;

    string strAddress = string.Format(BASE_ADDRESS_FORMAT_STRING, mServiceType.Name);
    Uri tcpBaseAddress = new Uri(strAddress);

    var binding = new NetTcpBinding(SecurityMode.Transport);
    binding.Name = mServiceType.Name;

    binding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
    binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;      

    host.Authorization.ImpersonateCallerForAllOperations = true;            
    host.AddServiceEndpoint(mServiceType.GetInterfaces()[0], binding, tcpBaseAddress);
    host.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexTcpBinding(), new Uri(strAddress + "/mex"));                
}

Oh, btw, I have tried using

channelFactory.CreateChannelActingAsLoggedOnUser(<endpointAddress>)

but it gives a nullreference-exception

A billion thanks in advance. /Robert

share|improve this question
    
Your client is configured to use NTLM, not kerberos - is that intended? Have you disabled anonymous access for IIS web site running SharePoint? It the SharePoint application running HTTP or HTTPS? What says the ULS log about the access denied error? –  Bernd Rickenberg Oct 30 '12 at 10:14

3 Answers 3

_ Hi Bernd

My draft post became over 2 pages, so I decided to cut some details, to get any replies at all.

I have tried AllowNtlm = false, but for some reason I get the error message "The remote server did not satisfy the mutual authentication requirement." when I run.

In IIS-Manager on the IIS-app I have only "Windows Authentication" and "Impersonation" Enabled, and Windows Authentication-provider is set to (only) Negotiate. I dont know how to force server to enable Kerberos. Anonymous auth is disabled both in the IIS-Subapp and the "Sharepoint 80"-site

Strangely enough I can set AllowNtlm to false when calling from test/console app.

The SP app (and everywhere else) is running http.

share|improve this answer
    
Ended up following this example. –  Robert Nov 7 '12 at 13:42

I ended up following this example (custom http binding) http://blogs.msdn.com/b/dtaylor/archive/2010/05/12/sharepoint-calculator-service-part-9-claims-auth.aspx

share|improve this answer
    
While this may theoretically answer the question, we prefer inclusion of the essential parts of the answer here, and to provide the link for reference. See answer for general guidelines. –  SPDoctor Aug 27 '13 at 10:50

Have you seen this article:

Connect a Client to SharePoint through a WCF Web Service with Kerberos Delegation http://blogs.msdn.com/b/florianmader/archive/2013/07/21/connect-a-client-to-sharepoint-through-a-wcf-web-service-with-kerberos-delegation-part-2.aspx

share|improve this answer
    
While this may theoretically answer the question, we prefer inclusion of the essential parts of the answer here, and to provide the link for reference. See answer for general guidelines. –  SPDoctor Aug 27 '13 at 10:50

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.