I create a WCF web service with a custom anchor endpoint and receive a stuck WS-Security header reception that is sent to me by the other side. We both follow the specifications developed by the UK National Health Service, so I cannot make any changes to the requirements.
The basic structure of the <wsse:Security> header should be as follows, according to the specification:
<wsse:Security> <wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurityutility-1.0.xsd" wsu:Id="6CCF6A2B-11A6-11DF-86D1-236A99759561" > <wsu:Created>2012-06-12T09:00:00Z</wsu:Created> <wsu:Expires>2012-06-12T09:15:00Z</wsu:Expires> </wsu:Timestamp> <wsse:UsernameToken> <wsse:Username>SomeUsername</wsse:Username> </wsse:UsernameToken> <wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wsssoap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis- 200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="30b91ede-35c2-11df-aac9-97f155153931 ">xxx...</wsse: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="#6CCF6A2B-11A6-11DF-86D1-236A99759561" /> <Transforms> <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> </Transforms> <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> <DigestValue>xxx...</DigestValue> </SignedInfo> <SignatureValue>xxx...</SignatureValue> <KeyInfo> <wsse:SecurityTokenReference> <wsse:Reference URI="#30b91ede-35c2-11df-aac9-97f155153931 "/> </wsse:SecurityTokenReference> </KeyInfo> </Signature> </wsse:Security>
In my web service, I tried using the following binding:
<customBinding> <binding name="wsHttpSoap11" > <textMessageEncoding messageVersion="Soap11WSAddressingAugust2004" /> <security authenticationMode="MutualCertificate"> </security> <httpTransport/> </binding> </customBinding>
(The reason I use customBinding is because I have to support both WS-Addressing and WS-Security on top of SOAP 1.1 , and got advice from this answer .)
If I run a sample request through Fiddler, I get the following error in my WCF trace:
Cannot find token authenticator for ' System.IdentityModel.Tokens.UserNameSecurityToken '. Tokens of this type cannot be accepted in accordance with the current security settings.
I believe this is because it cannot authenticate <UsernameToken> . If I changed the binding security to:
<security authenticationMode="UserNameForCertificate">
Then I get this error:
Cannot find token authenticator for ' System.IdentityModel.Tokens.X509SecurityToken '. Tokens of this type cannot be accepted in accordance with the current security settings.
I believe this is because now it cannot authenticate <BinarySecurityToken> !
So the question is:
- Are my assumptions correct regarding the cause of error messages (that it can only process one token in the current configuration)?
- How to configure it to accept both tokens?
Update
Thanks to @Yaron, a user binding extension has now been added, and UserNameSecurityToken and X509SecurityToken are checked .
However, it now fails at the stage where it validates the XML signature. Exception returned in HTTP response:
Error checking messages.
If I delve into the stack trace in the service trace viewer, I see:
System.Security.Cryptography.CryptographicException ...
Signature Verification Error.
in System.IdentityModel.SignedXml.VerifySignature (HashAlgorithm hash, Asymmetric strain warp matrix) in System.IdentityModel.SignedXml.StartSignatureVerification (Security CheckKey) ...
Can someone help me understand why this is happening? At the moment, I'm a little lost. I tried using some sample code to try to manually verify the signature, but says the signature is not valid. How can I be sure it is or not before I return to the supplier? Is this something that should work? Should we share some certificates somewhere along the line?