none
Self Signed certificates, WCF configuration, IIS configuration, certificates install on client RRS feed

  • Question

  • Hello,

    I'm looking for a end-to-end example of how to deploy a WCF service with self-signed certificate. The Authentication is using HTTP credentials (not SOAP). The service is deployed on Win2012R2 IIS (8.5). Client is a windows forms application running on win 7 machines. The client and servers are within the corporate firewall and we can install certificates on the users machines if needed. I found many helpful posting but none which cover this scenario end-to-end and I still can't make it work (we can make it work on a dev box...)

    Here are some more specific questions:

    1. What is the recommended method for creating a self-signed cert for the above scenario? In what store it should reside?
    2. How do we configure the site on IIS to use the cert?
    3. What should be the service configuration in web.config? We are using a custom validator for the users name and password (which is working on dev)
    4. What should be the configuration in the client app.config? Do we have to install the certificate on each client machine? If yes - how?
    5. Is there a way to test such a service with SOAP UI?

    I know these are a lot of questions, but we've been following so many blogs and MSDN articles and it still doesn't work (the error we currently get is "Could not establish trust relationship for the SSL/TLS secure channel with authority 'myhost:port').

    Thank you,

    Ken

    Monday, September 28, 2015 3:52 AM

Answers

All replies

  • Hi Ken Saraf,

    According to your description, from my experience is that you need to create a server-side

    certificate, when your add the reference to client and generate a proxy. It will  config a private

    key to  client app.config file. Like below:

    <configuration>
        <startup> 
            <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
        </startup>
        <system.serviceModel>
            <bindings>
                <wsHttpBinding>
                    <binding name="username">
                        <security>
                            <message clientCredentialType="UserName" />
                        </security>
                    </binding>
                </wsHttpBinding>
            </bindings>
            <client>
                <endpoint address="http://127.0.0.1:9999/calculatorservice" binding="wsHttpBinding"
                    bindingConfiguration="username" contract="ServiceTest.CalculatorService"
                    name="username">
                    <identity>
                        <certificate encodedValue="AwAAAAEAAAAUAAAAFaZfHFZxolGVE6oVy8GyqmXgx5IgAAAAAQAAAPECAAAwggLtMIIB2aADAgECAhAKgF6ThXq6kE82sNOgiLeaMAkGBSsOAwIdBQAwEjEQMA4GA1UEAxMHV0NGQ2VydDAeFw0xNDEyMjMwMjQ3NDhaFw0zOTEyMzEyMzU5NTlaMBIxEDAOBgNVBAMTB1dDRkNlcnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCRjc4YH9Vh8G0xS+rZzgdcTSL5P3+lwDpro5VWv1FvvaqDNi3E+b7mdCqjEFWkyYqCrpolj322XvL2BusRtkUzujeIkffWqBenuYlU5sEvGEHLwsdHARZP32K52jrCCLdSoI4JtU5uR2K3m5q5EvBcU56P/w0HKBtl05fZVzhXvQKQgFUbhWAqr2GC/usbJyDTrRTwf1OsE0ee1s0W9CQtgMqM7Pr+fsyz9TjiFmcTPH68lFiWitHAow/E4WMUKdGsAQ8QwBVZBjhimx+rnQiz68+tIL32vHCIk5WGT11zRVEjg4ZQksqkE53e6vR0o2QWXhPBADPkCRYJ5KQM8MfvAgMBAAGjRzBFMEMGA1UdAQQ8MDqAEKFTx/O/abeM/+ilVMmzbS2hFDASMRAwDgYDVQQDEwdXQ0ZDZXJ0ghAKgF6ThXq6kE82sNOgiLeaMAkGBSsOAwIdBQADggEBAGh02lU0DgK8Vf+4Mw0LGT9d8ht+LTj/X1lbP21lynWqrO+tQEtb9qa/Idcv4/ANG0m1rDcr9zvNBnav3hpACJK12gzqjE1I540Y/QwIUCVx91ahiFVInWaBNcR6LhvHGQkoUS5ggl0UeW1tzCJV9AMNvL2d01/aC09qM6ShLtHlSIocSq75UCUbW0cfqgSooCawuM3hUQhG5SG0B8rAhZUcVjl1WuRbUlla0H/2hUihosAz688xWxIv7JCDnix/aEVBsWNonO2KwmQ+JvIfwn2/qDpYVmqTHpoDeMntmFeOhyiCE0H5yMzjksmESjkSETESIMj4LNK3NQoX2D9l4yk=" />
                    </identity>
                </endpoint>
            </client>
        </system.serviceModel>
    </configuration>

    Then my server-side web.config file like below:

    <configuration>
        <startup> 
            <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
        </startup>
      <system.serviceModel>
        <behaviors>
          <serviceBehaviors>
            <behavior name="userNameBehavior">
              <serviceMetadata httpGetEnabled="true" httpGetUrl="http://127.0.0.1:9999/calculatorservice/metadata"/>
              <serviceDebug  includeExceptionDetailInFaults="true"/>
              <serviceCredentials>
                <issuedTokenAuthentication allowUntrustedRsaIssuers="true"></issuedTokenAuthentication>
                <clientCertificate>
                  <authentication certificateValidationMode="None"/>
                </clientCertificate>
                <serviceCertificate findValue="WCFCert" storeName="My" storeLocation="CurrentUser" x509FindType="FindBySubjectName"/>
                <!--custom validation-->
                <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Service1.MyValidator,Service1"/>
              </serviceCredentials>
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <bindings>
          <wsHttpBinding>
            <binding name="userBinding">
              <security mode="Message">
                <message clientCredentialType="UserName"/>
              </security>
            </binding>
          </wsHttpBinding>
        </bindings>
        <services>
          <service behaviorConfiguration="userNameBehavior" name="Service1.CalculatorService">
            <host>
              <baseAddresses>
                <add baseAddress="http://127.0.0.1:9999/calculatorservice/"/>
              </baseAddresses>
            </host>
            <endpoint address="" binding="wsHttpBinding" bindingConfiguration="userBinding"
                       name="username" contract="Contract1.ICalculator">
            </endpoint>
          </service>
        
        </services>
      
      </system.serviceModel>

    My custom username and password code like below:

    namespace Service1
    {
        class MyValidator:UserNamePasswordValidator
        {
            public override void Validate(string userName, string password)
            {
                //the follow code is testing only.u can read userName and password from DataBase.
                if (userName != "user" || password != "pwd")
                {
                    throw new Exception("Unknown Username or Password");
                }
            }
        }
    }
    

    My client code like this :

    namespace Client
    {
        class Program
        {
            static void Main(string[] args)
            {
                CalculatorServiceClient proxy = new CalculatorServiceClient();
                proxy.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode =
                    System.ServiceModel.Security.X509CertificateValidationMode.None;
                proxy.ClientCredentials.UserName.UserName = "user";
                proxy.ClientCredentials.UserName.Password = "pwd";
                bool flag = proxy.test();
                Console.WriteLine(flag.ToString());
                Console.ReadKey();
            }
        }
    }
    

    For more information, please refer to the following articles:

    1.Testing with client certificate authentication in a development environment on IIS 8.5

    2.WCF Service with custom username password authentication

    I hope that will be helpful to you.

    Best Regards,

    Grady

    Tuesday, September 29, 2015 2:19 AM
    Moderator
  • Hi Grady,

    Thank you for the detailed answer. It's very helpful.

    However, the first link you provided is for generating certificate on an XP machine which has Visual Studio on it. I'm looking for the exact same type of explanation but for a Windows 2012 R2 machine which does not have Visual Studio on it. Also the clients and server are on the same machine because this is a development environment while in my case, the client is on a separate machine. As I mentioned, we have it working in DEV and our problem is with deploying it to the TST/UAT environment - which is the same as PRD.

    Thank you,

    Ken.

    Wednesday, September 30, 2015 6:42 AM
  • Hi Ken Saraf,

    In my side, my os is windows 10, and my dev is visual studio 2013.

    So, I suggest you can refer to the following articles:

    1. SSL Certificates CSR Creation :: IIS 8 and IIS 8.5

    2.Obtain a Certificate on Windows Server 2008 R2 and 2012 (Without Using IIS)

    I hope that will be helpful to you.

    Best Regards,

    Grady

    Friday, October 2, 2015 7:29 AM
    Moderator
  • Just to let you know that we opened a case with Microsoft support and they were not able to solve the issue. We ended up buying a cert and it worked like a charm. Something with the self-signed certs wasn't configured properly and I still don't know what it was.

    The working configuration on the web.config is:

    <behavior name="SecureBehavior">
              <serviceCredentials>
                <serviceCertificate findValue="{subject_name}" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"/>
                <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="PIWrapper.UserNamePassValidator, PIWrapper" />
              </serviceCredentials>
    </behavior>
    <basicHttpBinding>
            <binding name="SecureBinding">
              <security mode="TransportWithMessageCredential">
                <message clientCredentialType="UserName"/>
              </security>
            </binding>
    </basicHttpBinding>
    
    <service behaviorConfiguration="SecureBehavior" name="PIWrapper.PIWrapperService">
            <endpoint address="" binding="basicHttpBinding" bindingConfiguration="SecureBinding" contract="BCH.WrapperService.IWrapperService"/>
    </service>
    
    I did not have to install the cert on the client machine or add anything special to the client app.config

    Hope it helps

    Ken

    

    Tuesday, October 27, 2015 5:21 AM