5
votes

Hi I made a WCF service hosted in Windows Azure project as WebRole.

My Service is secured with an SSL certificate and this works.
Now I want to add some extra security on my operation contract and if I do this (set a protection level) I get next error.

I need to configure some binding or something else to get this work but I don't know what and I don't know where.

Project info:

Error:

    The request message must be protected. This is required by an operation of the contract ('IService1','http://tempuri.org/').
    The protection must be provided by the binding ('BasicHttpBinding','http://tempuri.org/').

Architecture

enter image description here
ServiceConfiguration.Cloud.cscfg & ServiceConfiguration.Local.cscfg

<?xml version="1.0" encoding="utf-8"?>
<ServiceConfiguration serviceName="Azure" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="1" osVersion="*">
  <Role name="WCFServiceWebRole">
    <Instances count="1" />
    <ConfigurationSettings>
      <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="UseDevelopmentStorage=true" />
    </ConfigurationSettings>
    <Certificates>
      <Certificate name="Certificate1" thumbprint="51F357715F" thumbprintAlgorithm="sha1" />
    </Certificates>
  </Role>
</ServiceConfiguration>

ServiceDefinition.csdef

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="Azure" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="WCFServiceWebRole" vmsize="ExtraSmall" enableNativeCodeExecution="true">
    <Sites>
      <Site name="Web">
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1" />
          <Binding name="Endpoint2" endpointName="Endpoint2" />
        </Bindings>
      </Site>
    </Sites>
    <Endpoints>
      <InputEndpoint name="Endpoint1" protocol="http" port="80" />
      <InputEndpoint name="Endpoint2" protocol="https" port="8080" certificate="Certificate1" />
    </Endpoints>
    <Imports>
      <Import moduleName="Diagnostics" />
    </Imports>
    <LocalResources>
      <LocalStorage name="WCFServiceWebRole.svclog" sizeInMB="1000" cleanOnRoleRecycle="false" />
    </LocalResources>
    <Certificates>
      <Certificate name="Certificate1" storeLocation="LocalMachine" storeName="My" />
    </Certificates>
  </WebRole>
</ServiceDefinition>

Contract

[DataContract]
public class KlantenContract
{
    [DataMember]
    public int PARTYID { get; set; }

    [DataMember]
    public string firstName { get; set; }

    [DataMember]
    public string lastName { get; set; }

IService1.cs

namespace WCFServiceWebRole
{
    [ServiceContract(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
    public interface IService1
    {
        [OperationContract(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
        List<KlantenContract> GetAllKlanten(string firstName);
    }
}

Web.config

  <system.serviceModel>

    <bindings>
      <wsHttpBinding>
        <binding name="IService1">
          <security mode="Transport"></security>
        </binding>
        <binding name="Certificate1">
          <security>
            <message clientCredentialType="Certificate"/>
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>

    <services>
      <service name="Service1" behaviorConfiguration="ServiceBehavior">
        <endpoint address="https://127.0.0.1:8080/Service1.svc" binding="wsHttpBinding"
          name="Endpoint2" contract="IService1">
        </endpoint>
      </service>
    </services>

    <behaviors>
      <serviceBehaviors>

          <behavior name="ServiceBehavior">
            <serviceMetadata httpGetEnabled="true" />
            <serviceDebug includeExceptionDetailInFaults="false" />
            <serviceCredentials>
              <serviceCertificate findValue="CN=tempCert" />
            </serviceCredentials>
          </behavior>

          <behavior>
          <!-- 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="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
1

1 Answers

3
votes

If you set your service as EncryptAndSign, it must use secured transportation, for example HTTPS. I don't know in your last screenshot if you viewed the service through HTTP or HTTPS, but you have to use HTTPS.

If you wanted IIS to take care if the secured binding, you can just set the security mode to TransportWithCredentialOnly, and configured your web role to use your certificate to bind to 443, which I think you have done already, and then it should be OK.

Alternatively you can use Transport security and in the ServerCredential part you need to specify which certificate you want the WCF to use to create the secured transport.

I've never tried the message security mode but I think it should work, but you may need to specify the certificate as well, under the message security configuration element.