WCF HTTPS SSL Self Hosted Cert. How to Get Working Correctly?

11,605

Well from what I can tell you are missing several of the HTTPS metadata endpoint and behavior configurations necessary for hosting a WCF self-hosted service using SSL. The main steps to do what you need are the following:

  1. Create a self-signed certificate (for testing purposes) with a matching common name value of the domain name of your endpoint URL (best to use your machine name)
  2. Use netsh.exe to bind the port with your SSL certificate using it's thumbprint.
  3. Configure your WCF .config file to have the required SSL settings.

This is a rather lengthy process so rather than try and document every step here, I have a blog post that details what you need to get your WCF self-hosted service using SSL. This should help you see a working solution that you can then apply to your project:

Applying and Using a SSL Certificate With A Self-Hosted WCF Service

Share:
11,605
jordan
Author by

jordan

Updated on June 09, 2022

Comments

  • jordan
    jordan almost 2 years

    I am struggling to convert a silverlight application from HTTP to HTTPS using the WCF and a self signed certificate registered into IIS.

    Calls i have made in the Visual Studio 2010 Command Prompt:

     makecert -sv SignRoot.pvk -cy authority -r signroot.cer -a
        sha1 -n "CN=Dev Certification Authority" -ss my -sr localmachine    
    
    makecert -iv SignRoot.pvk -ic signroot.cer -cy end -pe -n
        CN="localhost" -eku 1.3.6.1.5.5.7.3.1 -ss my -sr
        localmachine -sky exchange -sp
        "Microsoft RSA SChannel Cryptographic Provider" -sy 12
    

    I have this as the end point (this is the call that still is not HTTP in Fiddler)

    <!-- Address that the Silverlight clients will connect to -->
    <!-- as specified in their web.config -->
    <add key="gatewayListeningHttpURI" value="http://localhost:10201/" />
    

    Current Server Config:

    <!-- set up binding for duplex service -->
    <bindings>
      <customBinding>
        <binding name="customDuplexBinding">
          <pollingDuplex duplexMode="MultipleMessagesPerPoll"
               maxOutputDelay="00:00:01"
       serverPollTimeout="00:01:00"
       inactivityTimeout="02:00:00"
       maxPendingMessagesPerSession="2147483647"
       maxPendingSessions="2147483647" />
          <binaryMessageEncoding>
            <readerQuotas
              maxDepth="2147483647"
              maxStringContentLength="2147483647"
              maxArrayLength="2147483647"
              maxBytesPerRead="2147483647"
              maxNameTableCharCount="2147483647" />
          </binaryMessageEncoding>
          <httpTransport
      maxBufferSize="2147483647"
      maxReceivedMessageSize="2147483647"
      transferMode="StreamedResponse"
                />
        </binding>
      </customBinding>
    
    </bindings>
    
    <behaviors>
      <endpointBehaviors>
        <!-- For Policy Service -->
        <behavior name="webHttpEndpointBehavior">
          <webHttp />
        </behavior>
      </endpointBehaviors>
    
      <serviceBehaviors>
        <behavior name="sb">
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <!-- This will solve a bug that happens if too many items are sent at once from the gateway to the client -->
          <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
          <serviceThrottling
          maxConcurrentCalls="200"
          maxConcurrentSessions="200"
          maxConcurrentInstances="200" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    
    <services>
      <service name="ME.Streets.WebGateway.DuplexService.DuplexService"
         behaviorConfiguration="sb">
        <endpoint
           address="basic"
           binding="customBinding"
           bindingConfiguration="customDuplexBinding"
           contract="ME.Streets.WebGateway.DuplexService.Interface.IDuplexServiceContract">
        </endpoint>
        <endpoint
            address=""
            binding="webHttpBinding"
            behaviorConfiguration="webHttpEndpointBehavior"
            contract="ME.Streets.WebGateway.DuplexService.Interface.IPolicyRetriever"/>
        <endpoint
            address="mex"
            binding="mexHttpBinding"
            contract="IMetadataExchange"/>
      </service>
    </services>
    

    Current Client Config:

    private DuplexServiceContractClient CreateDuplexServiceClient(EndpointAddress endPoint)
        {
            PollingDuplexBindingElement pollingDuplexBindingElement = new PollingDuplexBindingElement();
            pollingDuplexBindingElement.DuplexMode = PollingDuplexMode.MultipleMessagesPerPoll;
    
            #if DEBUG
            pollingDuplexBindingElement.ClientPollTimeout = TimeSpan.FromMinutes(15);
            pollingDuplexBindingElement.InactivityTimeout = TimeSpan.FromMinutes(14);
            #else
            pollingDuplexBindingElement.ClientPollTimeout = TimeSpan.FromMinutes(60);
            pollingDuplexBindingElement.InactivityTimeout = TimeSpan.FromMinutes(60);
            #endif
    
            HttpsTransportBindingElement httpsTransportBindingElement = new HttpsTransportBindingElement();
            httpsTransportBindingElement.MaxBufferSize = int.MaxValue;
            httpsTransportBindingElement.MaxReceivedMessageSize = int.MaxValue;
            httpsTransportBindingElement.TransferMode = TransferMode.StreamedResponse;
    
            CustomBinding binding = new CustomBinding(
                pollingDuplexBindingElement,
                new BinaryMessageEncodingBindingElement(),
            httpsTransportBindingElement);
    
            var dscc = new DuplexServiceContractClient(binding, endPoint);
    
            dscc.InnerChannel.OperationTimeout = TimeSpan.FromMinutes(5);
    
    #if DEBUG
            dscc.InnerChannel.OperationTimeout = TimeSpan.FromMinutes(15);
    #endif
            return dscc;
        }
    

    I have deployed my silverlight applicatoin into IIS and have added the HTTPS protocol to it so that i can reach it by adding HTTPS in front of the web address.

    Problem is still when i log onto the https site (https://localhost/FleetNew), I Still recieve the error of "Display MIxed Content"

    When i watch in fidler, it is the call localhost:10201 that is the unsecure http call.

    my netsh http show sslcert command brings me this:

    IP:port                 : 0.0.0.0:10201
    Certificate Hash        : 0fb891e03c857d1c50b63163e5a0b999ed757ea1
    Application ID          : {3d5900ae-111a-45be-96b3-d9e4606ca793}
    Certificate Store Name  : (null)
    Verify Client Certificate Revocation    : Enabled
    Verify Revocation Using Cached Client Certificate Only    : Disabled
    Usage Check    : Enabled
    Revocation Freshness Time : 0
    URL Retrieval Timeout   : 0
    Ctl Identifier          : (null)
    Ctl Store Name          : (null)
    DS Mapper Usage    : Disabled
    Negotiate Client Certificate    : Disabled
    
    IP:port                 : 0.0.0.0:443
    Certificate Hash        : 0fb891e03c857d1c50b63163e5a0b999ed757ea1
    Application ID          : {4dc3e181-e14b-4a21-b022-59fc669b0914}
    Certificate Store Name  : MY
    Verify Client Certificate Revocation    : Enabled
    Verify Revocation Using Cached Client Certificate Only    : Disabled
    Usage Check    : Enabled
    Revocation Freshness Time : 0
    URL Retrieval Timeout   : 0
    Ctl Identifier          : (null)
    Ctl Store Name          : (null)
    DS Mapper Usage    : Disabled
    Negotiate Client Certificate    : Disabled
    

    Please help me configure this correctly so that the call to locahost:20102 will work over ssl and HTTPS

  • jordan
    jordan over 11 years
    I do already have the ssl certificate bound to the port (see the last part of my question) and i have my certificate called "localhost" . I am just very stuck on how to correctly configure the WCF config files of the server and the client to work correctly
  • atconway
    atconway over 11 years
    I know it stinks to look at a large article like I posted and try it out, but you really should read through it and give it a try. Getting SSL to work for self hosted services took me a while and a combo of research so you should probably read the whole process. At a minimum, look at the configuration settings in the blog post compared to yours. It's mainly the server-side you need to worry about. The client-side will not require modifications after adding the service reference once you have a working SSL service.
  • jordan
    jordan over 11 years
    I actually used your blog post before coming here. ill read it again, but i think i needs some hands on help
  • atconway
    atconway over 11 years
    After looking at your configuration again I think you have the server and client configuration confused. The server is where you dictate SSL and expose an HTTPS endpoint, not the client. The client will auto configure its binding as I said once you add a service reference from a working SSL service. But in your server configuration, <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> does not indicate HTTPS, nor does the endpoint. My post states The entire service configuration is below: Look at the baseAddress too. It's all there.
  • jordan
    jordan over 11 years
    I have updated what i think is the current server/client config. i was looking at the wrong area for the server config for one. still not working, but ill give it another shot here. do you see anything worth changing in the updated original post?
  • jordan
    jordan over 11 years
    This didnt help at all, but it will probably be useful for future folks trying to attempt the cross over from http to https