Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting DefaultNetworkCredentials to pass through to WCF Service

I have a WCF service I have created in a WebApplication with the following configuration in web.config

<service name="RedwebServerManager.WebApplication.DesktopService"
           behaviorConfiguration="ServBehave">
    <endpoint
       address=""
        binding="basicHttpBinding"
        bindingConfiguration="basicBind"
        contract="RedwebServerManager.WebApplication.IDesktopService"/>
  </service>
</services>
<bindings>
  <basicHttpBinding>
    <binding name="basicBind">
      <security mode="TransportWithMessageCredential">
        <transport clientCredentialType="Windows"/>
      </security>
    </binding>
  </basicHttpBinding>
</bindings>

This service needs to take in WindowsCredentials in to get information in a database based upon the authenticated user. This service current has one method implementing an interface with the following signature

    [ServiceContract]
public interface IDesktopService
{
    /// <summary>
    /// Gets the clients.
    /// </summary>
    /// <returns>IEnumerable&lt;ClientServiceModel&gt;.</returns>
    [OperationContract]
    IEnumerable<ClientServiceModel> GetClients();
}

I have a Windows Forms application which is consuming the WCF service and I want to pass through the credentials of the current user using the application as this will all be sitting on our domain. The app.config is as follows

    <system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpBinding_IDesktopService">
              <security mode="TransportWithMessageCredential">
                <transport clientCredentialType="Windows" proxyCredentialType="Windows"/>
              </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="https://redwebservermanager.redweb.network/DesktopService.svc"
            binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IDesktopService"
            contract="ManagerService.IDesktopService" name="BasicHttpBinding_IDesktopService" />
    </client>
</system.serviceModel>

If I manually set the credentials username and password everything works correctly however I have been trying

managerService.ClientCredentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials

so that I can pass the current users credentials over but I keep getting an error on the call to GetClients() that the username and password is not set.

Can anyone help me? I also tried adding

[OperationBehavior(Impersonation = ImpersonationOption.Required)]

to the method but this made no difference.

like image 271
Scott Reed Avatar asked Apr 29 '16 11:04

Scott Reed


2 Answers

You can get the Username (and more information other than the password) using one of the following ways:

//1. 
System.Security.Principal.WindowsIdentity.GetCurrent();
//2.    
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
    WindowsPrincipal user = (WindowsPrincipal)System.Threading.Thread.CurrentPrincipal;
//3.    
WindowsIdentity ident = WindowsIdentity.GetCurrent();
    WindowsPrincipal user = new WindowsPrincipal(ident);

But, there is no way you can access the password of the user. Please refer to this question

Once you receive the Identity information, you can pass the username to WCF using OutgoingMessageHeaders, like:

MessageHeader<string> header = new MessageHeader<string>(userName);
        OperationContextScope contextScope =   new OperationContextScope(InnerChannel);
        OperationContext.Current.OutgoingMessageHeaders.Add(
        header.GetUntypedHeader("String", "System"));

And in the WCF service implementation you can read it like:

OperationContext context = OperationContext.Current;

            if (context != null)
            {
                try
                {
                    _LoginName = OperationContext.Current.IncomingMessageHeaders.GetHeader<string>("String", "System");          
                }
                catch
                {
                    _LoginName = string.Empty;
                }
            }

Please let me know if this helps or if you have any other questions.

Thank you, Soma.

like image 77
Soma Yarlagadda Avatar answered Oct 16 '22 09:10

Soma Yarlagadda


I feel like you can find your answer here: Intranet - web to remote wcf CredentialCache.DefaultNetworkCredentials not working. Basically you can't use Windows Authentication from Windows Forms application to WCF. You can only use it directly with WCF or Forms.

like image 29
Lesmian Avatar answered Oct 16 '22 10:10

Lesmian