WCF Message Security with Certification - wcf

I need to call as web services that is SSL encrypted and where the SOPA message has to be digital signed
I’m new to WCF, and this is what I have so far, but I still can get it right.
E.g. of SOAP message
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:mod="http://model.bxd.fi" xmlns:cor="http://bxd.fi/CorporateFileService">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1">
<wsse:BinarySecurityToken xmlns:wsu="http://docs.oasis- open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="CertId-9502902" ValueType="http://docs.oasis-pen.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message- security-1.0#Base64Binary">
S..=
</wsse:BinarySecurityToken>
<ds:Signature Id="Signature-22310861" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#id-23633426">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>yM2…TE=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>nc…brQ=</ds:SignatureValue>
<ds:KeyInfo Id="KeyId-7..8">
<wsse:SecurityTokenReference xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-00401-wss-wssecurity-utility-1.0.xsd" wsu:Id="STRId-2471808">
<wsse:Reference ValueType="http://docs.oasis-open.org/wss/2004/01/oasis- 200401-wss-x509-token-profile-1.0#X509v3" URI="#CertId-2902"/>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
</wsse:Security>
</soapenv:Header>
<soapenv:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity- utility-1.0.xsd" wsu:Id="id426">
<cor:getUserInfoin>
<mod:RequestHeader>…..<mod:RequestHeader>
<mod:ApplicationRequest>ASD..<mod:ApplicationRequest>
</cor:getUserInfoin>
</soapenv:Body>
</soapenv:Envelope>
Client Code
var cfs = new ServiceClient();
var data = new XmlDocument();
data.Load("C:\\Temp\\testxml2.xml");
var requestHeader = new RequestHeader
{
Timestamp = DateTime.Now,
SenderId = "1",
RequestId = "2",
UserAgent = "3",
ReceiverId = "4",
};
var uploadFileRequest = new UploadFileRequest
{
ApplicationRequest = Encoding.Unicode.GetBytes(data.OuterXml),
RequestHeader = requestHeader
};
var userResp = cfs.uploadFile(uploadFileRequest);
App.config
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="endpointCredentialsBehavior">
<clientCredentials>
<clientCertificate findValue="b7 ......... 99"
storeLocation="CurrentUser"
x509FindType="FindByThumbprint" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding" >
<security mode="TransportWithMessageCredential" >
<transport clientCredentialType="Certificate" />
<message clientCredentialType ="Certificate"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://..../Service"
behaviorConfiguration="endpointCredentialsBehavior"
binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding"
contract="FileServices"
name="WSHttpBindingEndPoint">
</endpoint>
</client>
</system.serviceModel>
I guess that the problem is the bindings (?)
security mode="Transport" = no security element in header.
security mode="Message" = https is invalid, expected http.
security mode="TransportWithMessageCredential" = security element in header BUT no message in the body part.
Or do I need to use WSE ?
Any help is appreciated
EDIT
new Config file
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="endpointCredentialsBehavior">
<clientCredentials>
<clientCertificate findValue="b7 ... 99"
storeLocation="CurrentUser"
x509FindType="FindByThumbprint" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<customBinding>
<binding name="NewBinding0">
<textMessageEncoding messageVersion="Soap11" />
<security authenticationMode="MutualCertificate" messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
</security>
<httpsTransport/>
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="https://..Services"
behaviorConfiguration="endpointCredentialsBehavior"
binding="wsHttpBinding"
bindingConfiguration="NewBinding0"
contract="FileServices"
name="WSHttpBindingEndPoint">
</endpoint>
</client>
</system.serviceModel>
<system.diagnostics>
..
</diagnostics>
</system.serviceModel>
</configuration>

Most details you need are in this WCF security post.
Use this binding:
<customBinding>
<binding name="NewBinding0">
<textMessageEncoding messageVersion="Soap11" />
<security authenticationMode="MutualCertificate" messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
</security>
<httpTransport />
</binding>
</customBinding>
And add this attribute to the data contract:
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReference1.SimpleServiceSoap", ProtectionLevel=System.Net.Security.ProtectionLevel.Sign)]
The post also specifies how to easily dismiss some of the errors you may encounter.

Related

How to configure service reference to point to Https, with MutualSSL setup?

In my project I recently changed my WCF service to use Https. It is configured to be a mutual ssl setup and the client and server certificates are both installed appropriately. Server side looks fine and even started fine in the browser as shown below.
However, when trying to configure the service reference from the WPF client side (service proxy that was previously added and generated). I get a 403 forbidden error code as shown below. Any idea why?
Here are my configurations.
WCF Server Side Config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceCredentials>
<serviceCertificate storeLocation="LocalMachine" x509FindType="FindByIssuerName" findValue="QuickFire Root Authority" />
</serviceCredentials>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="PushNotification_SignalR_PoC.WCF.PushNotificationService">
<endpoint binding="wsHttpBinding" bindingConfiguration="MutualSslLargeMessageBinding" contract="PushNotification_SignalR_PoC.WCF.IPushNotificationService" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="MutualSslLargeMessageBinding" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="Transport">
<transport clientCredentialType="Certificate"></transport>
</security>
</binding>
</wsHttpBinding>
</bindings>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<directoryBrowse enabled="true" />
</system.webServer>
</configuration>
WPF Client Side Config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WsHttpBinding_IPushNotificationService"
closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:30:00" sendTimeout="00:01:00"
allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647"
maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://localhost:44367/PushNotificationService.svc"
binding="wsHttpBinding" bindingConfiguration="WsHttpBinding_IPushNotificationService"
contract="ServiceProxy.IPushNotificationService" name="WsHttpBinding_IPushNotificationService" />
</client>
<behaviors>
<endpointBehaviors>
<behavior name="MutualSslBehavior">
<clientCredentials>
<clientCertificate storeLocation="CurrentUser" x509FindType="FindBySubjectName" findValue="QuickFire Test Client"/>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
If we want to call the service by adding service reference, we should add the MEX endpoint in the service endpoints on the server side. It could exchange metadata of the service over all platforms.
Like below,
<services>
<service name="PushNotification_SignalR_PoC.WCF.PushNotificationService">
<endpoint binding="wsHttpBinding" bindingConfiguration="MutualSslLargeMessageBinding" contract="PushNotification_SignalR_PoC.WCF.IPushNotificationService" />
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"></endpoint>
</service>
</services>
For details,
https://learn.microsoft.com/en-us/dotnet/framework/wcf/extending/how-to-configure-a-custom-ws-metadata-exchange-binding
Feel free to let me know if there is anything I can help with.

WCF: The incoming message was signed with a token which was different from what used to encrypt the body. This was not expected

I'm getting the following error:
The incoming message was signed with a token which was different from what used to encrypt the body. This was not expected.
I know this question has been asked before I have tried everything they asked. Not sure what else I need to do.
I'm thinking it has to do something with my app.config file:
<system.serviceModel>
<diagnostics>
<messageLogging
logEntireMessage="true"
logMalformedMessages="false"
logMessagesAtServiceLevel="true"
logMessagesAtTransportLevel="false"
maxMessagesToLog="3000"
maxSizeOfMessageToLog="2000"/>
</diagnostics>
<client>
<endpoint address="https://xxxxxx/ESARWS/CORETransactionService"
behaviorConfiguration="endpointCredentialBehavior" binding="customBinding"
bindingConfiguration="esar" contract="ESAR.CORETransaction"
name="CoreSoapPort">
<identity>
<dns value="xxxxx" />
</identity>
</endpoint>
</client>
<behaviors>
<endpointBehaviors>
<behavior name="endpointCredentialBehavior">
<clientCredentials>
<clientCertificate findValue="xxxxx"
storeLocation="CurrentUser"
storeName="My"
x509FindType="FindBySubjectName"/>
<serviceCertificate>
<authentication certificateValidationMode="ChainTrust"/>
<defaultCertificate findValue="xxxxxxxxx"
storeLocation="CurrentUser"
storeName="AddressBook"
x509FindType="FindBySubjectName" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<customBinding>
<binding name="esar" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:10:00">
<security
defaultAlgorithmSuite="Basic128"
authenticationMode="MutualCertificate"
requireSecurityContextCancellation="false"
allowSerializedSigningTokenOnReply="true"
enableUnsecuredResponse="true"
allowInsecureTransport="false"
requireDerivedKeys="false"
includeTimestamp="false"
securityHeaderLayout="Strict"
messageProtectionOrder="SignBeforeEncrypt"
messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
<secureConversationBootstrap />
<localClientSettings detectReplays="false"/>
</security>
<!--<mtomMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"
messageVersion="Soap12" writeEncoding="utf-8" maxBufferSize="2147483647">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
</mtomMessageEncoding>-->
<!--<mixedMessageEncoding messageVersion="Soap12"/>-->
<swaMessageEncoding innerMessageEncoding="textMessageEncoding" />
<httpsTransport />
</binding>
</customBinding>
</bindings>
<extensions>
<bindingElementExtensions>
<!--<add name="mixedMessageEncoding" type="CustomEncoderProject.MyNewEncodingBindingExtensionElement, CustomEncoderProject"/>-->
<add name="swaMessageEncoding"
type="Microsoft.Austria.WcfHelpers.SoapWithAttachments.SwaMessageEncodingElement, Microsoft.Austria.WcfHelpers.SoapWithAttachments" />
</bindingElementExtensions>
</extensions>
</system.serviceModel>
If server side developed in java, there are difference about implementation for C#.
I prefer try service with SAOP UI and check success request / response. Then log C# traffic with tool (for example fiddler) and check differences. Generally C# send certificate in different format then java.
You can try using a custom token authenticator. If you check the response, maybe you will be a cert in the BinarySecurityToken (#Base64Binary format). This isn't the ssl cert. It's the sign cert. Then, you can use it as your service certificate on credentials.
So, follow this: https://learn.microsoft.com/en-us/dotnet/framework/wcf/extending/how-to-create-a-custom-security-token-authenticator
and then customize this so:
Public Overrides Function CreateSecurityTokenProvider(ByVal p_oRequirement As SecurityTokenRequirement) As SecurityTokenProvider
Dim oRes As SecurityTokenProvider = Nothing
If p_oRequirement.TokenType = SecurityTokenTypes.X509Certificate Then
Dim direction = p_oRequirement.GetProperty(Of MessageDirection)(ServiceModelSecurityTokenRequirement.MessageDirectionProperty)
If direction = MessageDirection.Output Then
If p_oRequirement.KeyUsage = SecurityKeyUsage.Signature Then
oRes = New X509SecurityTokenProvider(Me._oCredenciales.ClientCertificate.Certificate)
Else
oRes = New X509SecurityTokenProvider(Me._oCredenciales.ServiceCertificate.DefaultCertificate())
End If
End If
Else
oRes = MyBase.CreateSecurityTokenProvider(p_oRequirement)
End If
Return oRes
End Function
I think this will help you.

WCF + SSL, getting empty result of method call

I have the following situation - i call remote service, written on Java from my WCF-client. This service has a certificate-based authentication, using SSL, and giving to all clients certificates in JKS format. I converted this certificate to P12 format and called to service. Сall does not raised an exception, but returned empty result.
Client-proxy i'm generated from service WSDL. Here is my config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="ClientEndPointBehavior">
<clientCredentials>
<clientCertificate storeLocation="CurrentUser" storeName="My" x509FindType="FindBySerialNumber" findValue="01234567"/>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="MyBinding" allowCookies="true">
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://myservice/services/"
binding="basicHttpBinding" bindingConfiguration="MyBinding"
contract="IContract" name="Contract" behaviorConfiguration="ClientEndPointBehavior"/>
</client>
</system.serviceModel>
</configuration>
What i'm doing wrong?
You would have to use CustomBinding for interoperability with java client or services.You could try any of the below bindings based on your mode of Authentication.
<customBinding>
<binding name="bindingName">
<textMessageEncoding messageVersion="Soap11" />
<httpsTransport authenticationScheme="Anonymous"
requireClientCertificate="true" />
</binding>
Try different authenticationScheme for the above
OR
<customBinding>
<binding name="bindingName">
<textMessageEncoding messageVersion="Soap11" />
<security authenticationMode="CertificateOverTransport" />
<httpsTransport requireClientCertificate="true"/>
</binding>
Please refer link for different options on authenticationMode
Hope this helps

Implementing WIF ActAs Scenario: The identity check failed for the outgoing message

So I'm trying to consume a WCF service from a website and pass the IClaimsIdentity the site got from an STS through to the service.
When I try to invoke a service method through an ActAs channel, I get the following error on the client (looking at trace logs, it never gets to the service, and the STS sends through all tokens correctly):
The identity check failed for the outgoing message. The expected
identity is
'identity(http://schemas.xmlsoap.org/ws/2005/05/identity/right/possessproperty:
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/thumbprint)' for
the 'http://localhost/MyWCFHost/MyService.svc' target endpoint.
I've got a custom IssuedTokenForCertificate binding and all the certificates are OK as far as I can see, it should work, but no dice. I'd appreciate another pair of eyes looking over my config and helping:
Consuming Web Site config:
<system.serviceModel>
<bindings>
<customBinding>
<binding name="CustomBinding_IMyService">
<security defaultAlgorithmSuite="Default" authenticationMode="IssuedTokenForCertificate"
requireDerivedKeys="true" includeTimestamp="true" messageSecurityVersion="WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10"
requireSignatureConfirmation="true">
<issuedTokenParameters tokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1">
<additionalRequestParameters>
<trust:SecondaryParameters xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
<trust:TokenType xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1</trust:TokenType>
<trust:KeyType xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://docs.oasis-open.org/ws-sx/ws-trust/200512/SymmetricKey</trust:KeyType>
</trust:SecondaryParameters>
</additionalRequestParameters>
<issuer address="http://localhost/MyCompany.SecurityTokenService/ActAsIssuer.svc"
binding="ws2007HttpBinding" bindingConfiguration="http://localhost/MyCompany.SecurityTokenService/ActAsIssuer.svc">
</issuer>
<issuerMetadata address="http://localhost/MyCompany.SecurityTokenService/ActAsIssuer.svc/mex" />
</issuedTokenParameters>
<localClientSettings detectReplays="true" />
<localServiceSettings detectReplays="true" />
</security>
<textMessageEncoding />
<httpTransport />
</binding>
</customBinding>
<ws2007HttpBinding>
<binding name="http://localhost/MyCompany.SecurityTokenService/ActAsIssuer.svc">
<security>
<message establishSecurityContext="false" />
</security>
</binding>
</ws2007HttpBinding>
</bindings>
<client>
<endpoint address="http://localhost/MyWCFHost/MyService.svc" binding="customBinding"
bindingConfiguration="CustomBinding_IMyService" contract="MyService.IMyService"
name="CustomBinding_IMyService">
<identity>
<!--<certificate encodedValue="AwAAAAEAAAAUAAAAV2ILlfzl9NIHEiGv1rUCSitq8I0gAAAAAQAAAP8BAAAwggH7MIIBaKADAgECAhBTTBmG1HyUkEDVFmVUxfDLMAkGBSsOAwIdBQAwFTETMBEGA1UEAxMKRXRhbmEgUm9vdDAeFw0xMjA5MjExMjE2MDRaFw0zOTEyMzEyMzU5NTlaMB8xHTAbBgNVBAMTFEV0YW5hIFNUUyBFbmNyeXB0aW9uMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC0lbzr1b1aNiXGhwKMTO58QbLbbKoUtTRkA4egMlmip1Vm46BnscWAMvXA5kyzuqK6Cw/5bel15i0pZXR4kjByKbSr65V0/ODGrkUHaYb5vT8RzCczYcgzJmPGWawMYYJT8PXLXHkFmZZGXFZhiUBzyNMWh8YH16I/wFtUgmaBAQIDAQABo0owSDBGBgNVHQEEPzA9gBAV68U+Vhoc0Nu9qPJXfJSRoRcwFTETMBEGA1UEAxMKRXRhbmEgUm9vdIIQgnOTDbZVCaJFTK8PPAGynTAJBgUrDgMCHQUAA4GBACHLr32oqkFjKGN/fqk2VnsNNIs9niHQ4Q6UbJ252YWf4wFIz9Ho/+ZdFxC4tSHxa/IMH0kzYpRL5p61Zd8/QeryWCStqvoNPwyapaY3g0Pkm6dy6NJ82kX5eJxLjdJp8MVadPJs4VA7Smf+e9lMMoONAGP07AvzAVhtiYK2yMmH" />-->
<certificateReference findValue="57620B95FCE5F4D2071221AFD6B5024A2B6AF08D" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" />
</identity>
</endpoint>
</client>
</system.serviceModel>
WCF Service config:
<system.serviceModel>
<diagnostics>
<messageLogging logMalformedMessages="true" logMessagesAtTransportLevel="true" />
</diagnostics>
<services>
<service name="RPWCFApp.MyService" behaviorConfiguration="MyServiceBehaviour">
<endpoint address="" binding="customBinding" bindingConfiguration="CustomBindingConfiguration_IssuedTokenOverTransport" contract="RPWCFApp.IMyService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehaviour">
<federatedServiceHostConfiguration />
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
<serviceCredentials>
<serviceCertificate findValue="81A5DB3796F48B00FAC37CE67D7D8CA43078B996" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<extensions>
<behaviorExtensions>
<add name="federatedServiceHostConfiguration" type="Microsoft.IdentityModel.Configuration.ConfigureServiceHostBehaviorExtensionElement, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</behaviorExtensions>
</extensions>
<bindings>
<customBinding>
<binding name="CustomBindingConfiguration_IssuedTokenOverTransport">
<security authenticationMode="IssuedTokenForCertificate" messageSecurityVersion="WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10">
<issuedTokenParameters keyType="SymmetricKey" tokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1">
<issuer address="http://localhost/MyCompany.SecurityTokenService/ActAsIssuer.svc" binding="ws2007HttpBinding" bindingConfiguration="IssuedTokenBinding" />
<issuerMetadata address="http://localhost/MyCompany.SecurityTokenService/ActAsIssuer.svc/mex" />
</issuedTokenParameters>
</security>
<textMessageEncoding />
<httpTransport />
</binding>
</customBinding>
<ws2007HttpBinding>
<binding name="IssuedTokenBinding">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="Windows" establishSecurityContext="false" />
</security>
</binding>
</ws2007HttpBinding>
</bindings>
</system.serviceModel>
Sorted out my problem by changing the binding in the service config to ws2007FederationHttpBinding instead of CustomBinding and update my client service reference.
<bindings>
<ws2007FederationHttpBinding>
<binding name="serviceBinding" receiveTimeout="05:00:00" sendTimeout="05:00:00">
<security mode="Message">
<message>
<issuerMetadata address="http://localhost/MyCompany.SecurityTokenService/ActAsIssuer.svc/mex"/>
</message>
</security>
</binding>
</ws2007FederationHttpBinding>
</bindings>
Then because I'm using self-signed certificates, I had to change the certificateValidationMode using the following endpoint behaviour in the client config:
<behaviors>
<endpointBehaviors>
<behavior name="MyServiceBehavior" >
<clientCredentials>
<serviceCertificate>
<authentication certificateValidationMode="PeerOrChainTrust"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
And finally I just had to ensure my certificate was in the Trusted People store and finally I get the correct IClaimsIdentity when invoking the service :)
Hope this helps someone out there, because it drove me nuts for a while...

WCF message security with certificate and both client and service signing

We are attempting to implement message security between a client and WCF service using x509 certificates. The client sends the soap security headers and the service verifies the headers as expected. The problem is that the service is not signing it’s response message with security headers which we need. I believe below includes all of the information that is needed but let me know if you need anything else. Thanks!
The service’s web.config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<customErrors mode="Off" />
</system.web>
<system.serviceModel>
<services>
<service name="RealIdCardService.AetnaNavigator" behaviorConfiguration="serviceCredentialBehavior">
<endpoint address="" contract="RealIdCardService.IAetnaNav" binding="wsHttpBinding" bindingConfiguration="InteropCertificateBinding"></endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="serviceCredentialBehavior">
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpsGetEnabled="true" />
<serviceCredentials>
<!--certificate storage path in the server-->
<serviceCertificate findValue="WcfClient" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="TrustedPeople" />
<issuedTokenAuthentication allowUntrustedRsaIssuers="true" />
<!--certificate storage path in the client-->
<clientCertificate>
<certificate findValue="WcfServer" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="TrustedPeople" />
<authentication certificateValidationMode="PeerTrust" revocationMode="NoCheck" />
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="InteropCertificateBinding">
<security mode="TransportWithMessageCredential">
<!--security mode of certificate
establishSecurityContext="true"-->
<message negotiateServiceCredential="true" algorithmSuite="Default" establishSecurityContext="false" clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
<system.web>
<compilation debug="true" />
</system.web>
<system.webServer>
<handlers>
<remove name="StaticFile" />
</handlers>
</system.webServer>
</configuration>
The client’s app.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior>
<!--
The clientCredentials behavior allows one to define a certificate to present to a service.
A certificate is used by a client to authenticate itself to the service and provide message integrity.
This configuration references the "client.com" certificate installed during the setup instructions.
-->
<clientCredentials>
<clientCertificate findValue="WcfServer" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="TrustedPeople"/>
<serviceCertificate>
<defaultCertificate findValue="qanav2.sourceonedirect.com"
storeLocation="LocalMachine"
storeName="TrustedPeople" x509FindType="FindBySubjectName" />
<authentication revocationMode="NoCheck" certificateValidationMode="PeerTrust"
trustedStoreLocation="LocalMachine" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_RealIdCardService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="655360"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="1638400"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Certificate" negotiateServiceCredential="true"
algorithmSuite="Default" establishSecurityContext="false" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://qanav2.sourceonedirect.com/AetnaNavigator/RealIdCardService.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_RealIdCardService"
contract="RealIdCardService" name="WSHttpBinding_RealIdCardService" />
</client>
</system.serviceModel>
</configuration>
The request from the client showing the message security:
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<a:Action s:mustUnderstand="1">http://service.sourceOne.realIdcard.com/RealIdCardService/getImage</a:Action>
<a:MessageID>urn:uuid:5d1170db-cc7f-485b-9d19-e88edb49a957</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1" u:Id="_1">https://qanav2.sourceonedirect.com/AetnaNavigator/RealIdCardService.svc</a:To>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<u:Timestamp u:Id="_0">
<u:Created>2011-08-11T16:39:51.548Z</u:Created>
<u:Expires>2011-08-11T16:44:51.548Z</u:Expires>
</u:Timestamp>
<o:BinarySecurityToken u:Id="uuid-8c46f875-8e7c-449d-ba8b-c9263a04db89-1" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">MIIBsTCCAV+gAwIBAgIQW2xiwVBnILpOlvTOe4BlezAJBgUrDgMCHQUAMBYxFDASBgNVBAMTC1Jvb3QgQWdlbmN5MB4XDTExMDgxMTE0NTA1M1oXDTM5MTIzMTIzNTk1OVowFDESMBAGA1UEAxMJV2NmU2VydmVyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4xaSGyke2NPJfXOHtZBz3yHXIjl0nA4WxKWY5Ettgs0DxUU7UKONgEKTloYnkmmiiHjRHzbClfaAbPrDQEe/DihmohWKDGa6aQ1Cat+CsZDGDgLhIcv85n1uLNriA5CJ2ebwgOoh6VxOLOQvjfNGBGfQBSZDe7DMOPntjO7ryhQIDAQABo0swSTBHBgNVHQEEQDA+gBAS5AktBh0dTwCNYSHcFmRjoRgwFjEUMBIGA1UEAxMLUm9vdCBBZ2VuY3mCEAY3bACqAGSKEc+41KpcNfQwCQYFKw4DAh0FAANBACfb7CnUN1dfyAgWbrxgwMr7wZgUo467YgT2+nOwiWlbbYJcqTx/5FkeVg3XXsaI2VINhUURrzvtJxFosKDzNR4=</o:BinarySecurityToken>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#_0">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>3Lo6p2VdFuYvSkrkqqxY06OseoM=</DigestValue>
</Reference>
<Reference URI="#_1">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>n/l/ydDWJXU8w/T5oZhXNoH2ZI0=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>cLvhF1zEuaizz+SyaqKRWDmE/HF64ODiP0E6B1jEkRWwNdyp7qwgtZaTQj8qcJKYGi76HpZm6DOd+Re0561h/o8o/vD+ijVHvMZc0AF12MN/HgItNBmYF6ify0y6g9PLlc0SFCGc/1aeLDj5yZylYTmMdqgps77q0kCV8s6hmWo=</SignatureValue>
<KeyInfo>
<o:SecurityTokenReference>
<o:Reference ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" URI="#uuid-8c46f875-8e7c-449d-ba8b-c9263a04db89-1"/>
</o:SecurityTokenReference>
</KeyInfo>
</Signature>
</o:Security>
</s:Header>
<s:Body>
<getImage xmlns="http://service.sourceOne.realIdcard.com/">
<arg0 xmlns:i="http://www.w3.org/2001/XMLSchema-instance"></arg0>
</getImage>
</s:Body>
</s:Envelope>
The response from the service without the certificate based security:
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<a:Action s:mustUnderstand="1">http://service.sourceOne.realIdcard.com/RealIdCardService/getImageResponse</a:Action>
<a:RelatesTo>urn:uuid:5d1170db-cc7f-485b-9d19-e88edb49a957</a:RelatesTo>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<u:Timestamp u:Id="_0">
<u:Created>2011-08-11T16:39:57.496Z</u:Created>
<u:Expires>2011-08-11T16:44:57.496Z</u:Expires>
</u:Timestamp>
</o:Security>
</s:Header>
<s:Body>
<getImageResponse xmlns="http://service.sourceOne.realIdcard.com/">
<getImageResult xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<CumbID>W261748481</CumbID>
<HMOID i:nil="true"/>
<IDCardImage>/9j/QAxb/wATayS9uZhG </IDCardImage>
<MailDate>7/1/2011 12:00:00 AM</MailDate>
</getImageResult>
</getImageResponse>
</s:Body>
</s:Envelope>
Your security setting is completely wrong based on your description. You want signatures in message? => you need message security but you are using transport security and only passing certificate as client identification. That has several implications:
Client connects to service over HTTPS - it validates trust to certificate used by service to build HTTPS connection
HTTPS itself (transport security) ensures encryption and integrity on the transport level
Certificate is only for client authentication - service doesn't have any certificate (certificate you configured is not used).
Client passes the certificate (public key) to the service and use its private key to sign headers.
Service receives the certificate and validate that it trust it
Service uses received public key to validate signatures
Service process the request and returns response
Service doesn't have any own certificate and client doesn't expect any => it cannot sign headers (client certificate cannot be used as well because service doesn't know clients private key)
Client receives the response and it is simply trusted because it returns over established HTTPS connection
If you want to have signatures in both request and response you must move to full message security (HTTPS will not be needed) which means changing security mode from TransportWithMessageSecurity to Message. After that both client and service will have its own certificate and use them to secure each message separately. By default whole content of your message will be also encrypted and signed. If you don't want it you must configure ProtectionLevel on your contracts.