4

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

1
  • 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? Commented Oct 30, 2012 at 10:14

3 Answers 3

2

_ 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.

1
  • Ended up following this example.
    – Cowborg
    Commented Nov 7, 2012 at 13:42
0

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

1
  • 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
    Commented Aug 27, 2013 at 10:50
0

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

1
  • 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
    Commented Aug 27, 2013 at 10:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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