Password data in ICredentials can't be passed from a WCF client to the WCF service in the .NET Framework 4.5

Symptoms

In a Windows Communication Foundation (WCF) client, you create a new ICredentials interface from the NetworkCredential class by using the username and password that are specified. Then, you make a call to a WCF contract method that takes ICredentials as an argument. You find that after you cast the ICredentials that are received in the WCF service back to a network credential, the Password property holds an empty string. However, the Username property is still holding a valid, correct value. 

Cause

This is a known issue that was introduced in the Microsoft .NET Framework 4.0 when a new property, SecurePassword, was added to the NetworkCredential class. This property overwrites the original password string when the SecurePassword property is deserialized on the service side. The SecurePassword property is of type SecureString. By design, it isn't serialized and sent. However, it overwrites the original password string by using an empty value. This behavior is also by design.

Resolution

To fix this issue, you have to pass the username and password information to the service independently of the network credential. You can do this by creating an application-defined object to hold the credentials and to pass the credentials to a new WCF service method that accepts the object as a method argument. Because this application-defined object contains sensitive information, we recommend that the data be sent over an encrypted connection to the WCF service by using either https transport security or message layer security.

More Information

The following example shows a WCF service that reproduces the issue. The WCF service has the following contract:

[ServiceContract]
[ServiceKnownType(typeof(NetworkCredential))]
public interface IService
{

    [OperationContract]
    string GetData(ICredentials value);
}

A client is using the service as follows:

iCredService.ServiceClient svcClient = new iCredService.ServiceClient();
ICredentials iCred = new System.Net.NetworkCredential("ABC", "1234");
string outCome = outCome = svcClient.GetData(iCred);

Using Visual Studio and setting a breakpoint at the service the value. Password will be empty. When you examine the Microsoft Visual Studio locals windows, you see the following text:

-   value {System.Net.NetworkCredential} System.Net.ICredentials {System.Net.NetworkCredential}
-      [System.Net.NetworkCredential] {System.Net.NetworkCredential} System.Net.NetworkCredential
 Domain  "" string
 Password "" string
+ SecurePassword {System.Security.SecureString} System.Security.SecureString
 UserName "ABC" string
Eigenschaften

Artikelnummer: 3082119 – Letzte Überarbeitung: 28.08.2015 – Revision: 1

Feedback