I get mails almost on a daily basis from people asking me how to build a
Wcf client to consume a service of framework X (usually axis or wsit
but others as well). After getting hundreds of these mails in the recent
years I conclude that there is a single most common setting which most
people need. There are also common confusions that a lot of people
stumble on in their first try. In this post I will present the common
setting, and what can (and will) go wrong.
The mails I get usually start with this soap sample which people want wcf to send:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<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="uuid-91102774-2ee8-4344-bbb7-77ea93c8f772-1">
<u:Created>2012-06-07T11:15:16.163Z</u:Created>
<u:Expires>2012-06-07T11:20:16.163Z</u:Expires>
</u:Timestamp>
<o:BinarySecurityToken u:Id="uuid-4b4d1ed9-b08b-4ba9-ba67-d755cae5d838-2" 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">MIIBxDCCAW6gAwIBAgIQYpjr4FOk3IFNSd3lJj6ItzANBgkqhkiG9w0BAQQFADAWMRQwEgYDVQQDEwtSb290IEFnZW5jeTAeFw0wMzA3MDgxODQ4MTBaFw0zOTEyMzEyMzU5NTlaMB8xHTAbBgNVBAMTFFdTRTJRdWlja1N0YXJ0U2VydmVyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLkqglArInukRlDwXbcjN3zxfsjeaLd+IvfyD5o35pUjpTkPwPXmApScr8UVQxB5JDRSVlMz1lUQ6CBLFLGIAQOpbPKn2oul3VmKAf9nRQf9PLU+biWozZXkhebIya43D75r5+5NUq1RbQiCC4qIobRqUdg6adujBY333wJy4YgwIDAQABo0swSTBHBgNVHQEEQDA+gBAS5AktBh0dTwCNYSHcFmRjoRgwFjEUMBIGA1UEAxMLUm9vdCBBZ2VuY3mCEAY3bACqAGSKEc+41KpcNfQwDQYJKoZIhvcNAQEEBQADQQAGSGNKz1gZqbXN8JYl0PQM7ngkHfW1mQ88NRYADmoHw5A/rUZDHAPs5HLSn3i5iXlRwT91v3SU6iuaAid+Mwyq</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="#_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>HA59hr6KPuBjJCzDi5OoaBdXfd4=</DigestValue>
</Reference>
<Reference URI="#uuid-91102774-2ee8-4344-bbb7-77ea93c8f772-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>x1IDhXSAw2z1xoRlXzuhyPIZnAM=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>IptFCEQ6whR+8kACLDDgJ5dsc6uYzCeQan3DG1pS2cnG2geP4v606m7u88938Bcm56wJa9U6xZO9SzXTC10u41OcwFCanwMMk5Y/wMEwt6W2F1WUTYr6OjUNA/slomRvYNkzoZ6AXu2YkhdXe+16fdAn7FmrxDRtY/Q8RgAhdjo=</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-4b4d1ed9-b08b-4ba9-ba67-d755cae5d838-2" />
</o:SecurityTokenReference>
</KeyInfo>
</Signature>
</o:Security>
</s:Header>
<s:Body u:Id="_1">
<EchoString xmlns="http://tempuri.org/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<s>1</s>
</EchoString>
</s:Body>
</s:Envelope>
|
Optionally ssl is also used.
The wcf setting required here is a custom binding with an authentication mode of "mutualCertificate":
1
2
3
4
5
6
7
8
|
<customBinding>
<binding name="NewBinding0">
<textMessageEncoding messageVersion="Soap11" />
<security authenticationMode="MutualCertificate" messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
</security>
<httpTransport />
</binding>
</customBinding>
|
(where https may be used instead of http)
Confusion 1: A wrong soap version by you can cause the server to
return different kinds of exceptions. Make sure the "messageVersion"
property on the textEncodingElement fits your needs. In particular if no
ws-addressing headers are used (To, ReplyTo, MessageID and Action) then
use "Soap11" (as above) or "Soap12" without any ws-addressing version.
Confusion 2: The proxy may throw this exception:
The client certificate is not provided. Specify a client certificate in ClientCredentials.
That's an easy one, you must confiugure a client certificate which is
pretty basic for a signing scenario. You can do it from code or config.
Here is the config version:
1
2
3
4
5
|
<behavior name="NewBehavior0">
<clientCredentials>
<clientCertificate findValue="CN=WSE2QuickStartServer" storeLocation="LocalMachine" />
</clientCredentials>
</behavior>
|
Confusion 3: You still get the same error after you have defined
the certificate. In this case make sure you have configured the endpoint
to use the behavior:
1
|
<endpoint ... behaviorConfiguration="NewBehavior0" ... />
|
Confusion 4: When I use mutualCertificate authentication mode I
define my client certificate. I do not have a server certificate to
define. My proxy is not sending anything and throws this error:
The
service certificate is not provided for target
'http://localhost/MyWebServices/Services/SimpleService.asmx'. Specify a
service certificate in ClientCredentials.
The issue is that mutualCertificate always requires you to define a
server certificate. In some cases you may not need it. In such cases it
is ok to define some dummy certificate as the server certificate, even
can be the same certificate you use for the client:
1
2
3
4
5
6
|
<clientCredentials>
<clientCertificate findValue="CN=WSE2QuickStartServer" storeLocation="LocalMachine" />
<serviceCertificate>
<defaultCertificate findValue="CN=WSE2QuickStartServer" storeLocation="LocalMachine" />
</serviceCertificate>
</clientCredentials>
|
Of course you may also do so from code.
Confusion 5: You may get this error:
"The
X.509 certificate CN=WSE2QuickStartServer chain building failed. The
certificate that was used has a trust chain that cannot be verified.
Replace the certificate or change the certificateValidationMode. A
certificate chain processed, but terminated in a root certificate which
is not trusted by the trust provider.\r\n"
This typically mean the server certificate you have defined is not
trusted by your machine. In the case that you have defined a dummy
server certificate (see confusion 3) or in other cases - at your risk
and for testing purpose only - you can turn off this validation by
setting certificateValidationMode to None.
Confusion 6: I am getting a good response from the server but the proxy throws this exception:
The incoming message was signed with a token which was different from what used to encrypt the body. This was not expected.
Congratulations, turns out you need to define a real server certificate
anyway (so confusion 2 does not apply). You should get it from the
service author. But if you don't there a nice trick to infer the
certificate by extracting the value of the binary security token from
the message and saving it to disk (in binary form)
as alluded here.
Confusion 7: I am getting a good response from the server but the proxy throws this exception:
Security
processor was unable to find a security header in the message. This
might be because the message is an unsecured fault or because there is a
binding mismatch between the communicating parties. This can occur if
the service is configured for security and the client is not using
security.
This means the service is not signing the response even though you sent a
signed request. In .Net 4+ you can turn off the secured response
requirement by toggling the security channel in your custom binding:
1
|
<security ... enableUnsecuredResponse="true" ... />
|
Confusion 8: When I use mutualCertificate I see my proxy sends a
message in a very different from what I need. In particular there is no
signature but only encryption, something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<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="uuid-548fbf32-9114-4e81-b11d-de6199497c37-1">
<u:Created>2012-06-07T11:40:22.488Z</u:Created>
<u:Expires>2012-06-07T11:45:22.488Z</u:Expires>
</u:Timestamp>
<o:BinarySecurityToken u:Id="uuid-d305f392-1c11-4a82-bff6-151dedc22034-2" 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">MIIBxDCCAW6gAwIBAgIQYpjr4FOk3IFNSd3lJj6ItzANBgkqhkiG9w0BAQQFADAWMRQwEgYDVQQDEwtSb290IEFnZW5jeTAeFw0wMzA3MDgxODQ4MTBaFw0zOTEyMzEyMzU5NTlaMB8xHTAbBgNVBAMTFFdTRTJRdWlja1N0YXJ0U2VydmVyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLkqglArInukRlDwXbcjN3zxfsjeaLd+IvfyD5o35pUjpTkPwPXmApScr8UVQxB5JDRSVlMz1lUQ6CBLFLGIAQOpbPKn2oul3VmKAf9nRQf9PLU+biWozZXkhebIya43D75r5+5NUq1RbQiCC4qIobRqUdg6adujBY333wJy4YgwIDAQABo0swSTBHBgNVHQEEQDA+gBAS5AktBh0dTwCNYSHcFmRjoRgwFjEUMBIGA1UEAxMLUm9vdCBBZ2VuY3mCEAY3bACqAGSKEc+41KpcNfQwDQYJKoZIhvcNAQEEBQADQQAGSGNKz1gZqbXN8JYl0PQM7ngkHfW1mQ88NRYADmoHw5A/rUZDHAPs5HLSn3i5iXlRwT91v3SU6iuaAid+Mwyq</o:BinarySecurityToken>
<e:EncryptedKey Id="_0" xmlns:e="http://www.w3.org/2001/04/xmlenc#">
<e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" xmlns="http://www.w3.org/2000/09/xmldsig#" />
</e:EncryptionMethod>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<o:SecurityTokenReference>
<X509Data>
<X509IssuerSerial>
<X509IssuerName>CN=Root Agency</X509IssuerName>
<X509SerialNumber>131058356848670871637284859017179334839</X509SerialNumber>
</X509IssuerSerial>
</X509Data>
</o:SecurityTokenReference>
</KeyInfo>
<e:CipherData>
<e:CipherValue>Ih/rYpTJCYcWl2O37Bt8yIZz/gbGWcXfVwENGLwPRRibETb47CavbkDRm+7trNFUGCXZ57ToYv4h0N+9e5RoZ9K3VirpE3RsSjBTxZfpy77UNsp9BHyq5HBwXOHc/xycRPCfs22n2gvfyrrzuYK1yaZdlFpN96DI8MRP3DSeXCw=</e:CipherValue>
</e:CipherData>
<e:ReferenceList>
<e:DataReference URI="#_2" />
<e:DataReference URI="#_3" />
</e:ReferenceList>
</e:EncryptedKey>
<e:EncryptedData Id="_3" Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns:e="http://www.w3.org/2001/04/xmlenc#">
<e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
<e:CipherData>
<e:CipherValue>zOfuDdN4HfBMeYRcxBN+H6Koaz/hAU0ddOTAnqNL997OF0bxhzdZ+KdYplMqRt9hR0Sops7/fU6jxzKTB74Q1M4hpun6JZoTdYffpslnt4ozNHviArZv6xkaw/MBdE5Q3bMQCj2h0/ddRs/H9T9z0/RAjB0i1S3hZArXHRPgaSKJGDn6a0cpUxGtq89CONpKYm6vgLcZXqwUNwRUbyTNvFWqYUtctPQjFphRLSGD4V73slpFx0nGAXtsv3goq/Ygh5w1j021ECPkYxnxtZwwkNdSo2idCaOa1PtUgUUITn1IghOva3o0q8L4eHVqk4M9Y4f2jgKJywKU2eRbich3bCbIQBBxhOP35IBNX0m/7Vq1GusI+nHzoulUEuEwSKOt5pc+XJkiqPk06SUCsugRRC2OAIYY83ewYib5YBP1i0ypI/Qdryl5UDv26j6uEwJ1zWDBH1RsPKkCqKCL2VMhw+RJBlQgs7Uq2KPiGr9sKVoYBBr3F/n1h8+zhsGn7RIt8vqt0AzlyIkTVIYYe07yNDt5fF7Ceg1u/ydmP4nItlv6Za+v82cWM1EZp1nsvOI4tfiyZsdT7L3RTxWOVnwOaK6MNT/110cC8VMJKeB0zyDfCahrUnFt9rvTY2sS7/r0VogsS7L0cv0pRsWHetxDMZGg2X++KgdfZUNdR8Nf+vDOFAEqjgh+elA+ytLu4RpOgdXFx9GiZLhpaPk8IBaYcfp1qmKD/WZE5K/Rn8EbkR/XrJAU4hbMOPV9q/2ua6yhtbQ8eAoN3UD+8aPh9FkBEKcQIbo1KG0E1ENnwuInyi8J/QLiS/Lh5Z672c+twusJ3dA4I5Sz4nRnC9h66FhSsRhfmCzLf5bEJ9pjNeCc3gnBKFNIwj6PiotCOI21liWijbRloKrxpCh/U4lH7ALuoSzj6QAmqUi/krZeUG4Yw3h7P+a4uPRsFtfPDe0dDDrTRMXPdVEE9yf5RIr33no0qzuOAKNapZPKdiqSLsr5trCpZ9Jl3US6iwZdIRUhiQD44NoMd37RcU+BCbmWOStfgVr72JbJ6FG2V2C5Xp8//YTpainRvHCXfTzuEnAWrPn88Pq5zv9xxXCOSDtMpBrkXKIC+MTje8T6CJPXQ2hDFBoN21UFmZdKuzYd5BpFGBXYQjSc/jtI/G9a4/QaUdZ3ljbogAqariVe841PFOxETHsdJl1Q4HU6EU0wl9ew/zjZjMOggXsjsw74DjEsUqb+NQqS+wX8koafaxtYNqZ5HSLvzA58XpenbIM6iaZjiSm7pKJLUpj2WIjXwaFCOWi7FuPhhuRxM1o4UVAWa/GhWmfDnvUQdmH+/sFuVs7eTsYATrmfMgvfRqzkeux2geQKwpJqfYZDenWslhmvc17OYwCknSyhHGxQqV0fT6Zfjc0xIpkR5n0ntLfqUzVGpXEcgY6YvH/WkdpTn1bIeSpb7g8upEnPdU2FxiqUt+xZCyOQlZWxqHlgJX569B3AsbenX8m3IH5DxHKmeYnxI/lUL9xNE2DztOarfL/CbFnd6YH/LjwU3PSqw5oRF5HzucHtZ8TSe48X85Fx8VkLN2AdLQkg6D641K+DweU7XD2wqjdnnylUsvsRvP7MqAkH2dhtz15Rt4128S8vpHuy3lAQVGWvt+COH4XwvL+RGmQvztEY7IUsBHyvCGWwCGlr3AY8WEekfRI3AFEOhLYGk6j9V9B9Is/7nbKf7xUQX6+9M7dM2VN7JGyURdxMa1Sh9/6N1f+Dp8RKE4tXYuoaTQcYtjk=</e:CipherValue>
</e:CipherData>
</e:EncryptedData>
</o:Security>
</s:Header>
<s:Body u:Id="_1">
<e:EncryptedData Id="_2" Type="http://www.w3.org/2001/04/xmlenc#Content" xmlns:e="http://www.w3.org/2001/04/xmlenc#">
<e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
<e:CipherData>
<e:CipherValue>g+XE2JCzHM3HLl6PD7FYzhqrIJ0lCvEECLox0BnOQsHfoj5SqJx/k9XG7day30kPlzd0HhYJZ7UUak4hLDUoMUE5YYOQ4cyWHMThrHdxVgjqz+RyjKXcdgZ/8QZDF4c90RaaycJFShAX0K5zsibsZVq7jhhUv2mOvmBWGhQg4hsjolJSK+keOIRn9yc8ib6S</e:CipherValue>
</e:CipherData>
</e:EncryptedData>
</s:Body>
</s:Envelope>
|
What you need to know is that by default messages will be signed AND
encrypted, and moreover the encryption will also encrypt the signature
and "hide" it from your eyes. The solution is to set the correct
protection level on your contract:
1
|
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReference1.SimpleServiceSoap", ProtectionLevel=System.Net.Security.ProtectionLevel.Sign)]
|
btw while interoperating with some java stacks you will know you are in confusion #8 if you get this error:
General security error (WSSecurityEngine: No crypto property file supplied for decryption)
Confusion 9: After applying the mitigation to confusion 7 the
outgoing message is still not in the desired format. In particular the
message is not signed by the binary token by a derived token, and there
is a primary and a secondary signature instead of just one:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPoy+E8yagEyJCs4I1Ca8GKX4AAAAA7ygFR3BFV0SoLPqFyQuvfdhhuzYv9dZKp8tKXMV1R88ACQAA</VsDebuggerCausalityData>
<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="uuid-162e5c78-b008-4cec-ba06-2640994e2742-2">
<u:Created>2012-06-07T11:43:22.343Z</u:Created>
<u:Expires>2012-06-07T11:48:22.343Z</u:Expires>
</u:Timestamp>
<e:EncryptedKey Id="uuid-162e5c78-b008-4cec-ba06-2640994e2742-1" xmlns:e="http://www.w3.org/2001/04/xmlenc#">
<e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" xmlns="http://www.w3.org/2000/09/xmldsig#" />
</e:EncryptionMethod>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<o:SecurityTokenReference>
<o:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#ThumbprintSHA1">h9ksyrcUww2w4LrmubC2W11t988=</o:KeyIdentifier>
</o:SecurityTokenReference>
</KeyInfo>
<e:CipherData>
<e:CipherValue>H1YPrRNeA+g2QysYqzb07pKicWFOCbTdINKEzmoGKJV4vHNpVjDxTMTJTmZs6tZVJ3E2U29AMhrN83dxJni80219WMjO/VNmlRS77Pfm8/82NR90qyieFoSunyTOEWSEFJyKUyw9J071mzqT/VI9/mjFO6X4XRuJA5R8YVM5yQc=</e:CipherValue>
</e:CipherData>
</e:EncryptedKey>
<c:DerivedKeyToken u:Id="_0" xmlns:c="http://schemas.xmlsoap.org/ws/2005/02/sc">
<o:SecurityTokenReference>
<o:Reference URI="#uuid-162e5c78-b008-4cec-ba06-2640994e2742-1" />
</o:SecurityTokenReference>
<c:Offset>0</c:Offset>
<c:Length>24</c:Length>
<c:Nonce>swheLIk6EUc6zA1Ukzwu6A==</c:Nonce>
</c:DerivedKeyToken>
<o:BinarySecurityToken u:Id="uuid-5721d2b5-ca82-4ddb-9f1f-33e0d77c8492-1" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3">MIIBxDCCAW6gAwIBAgIQYpjr4FOk3IFNSd3lJj6ItzANBgkqhkiG9w0BAQQFADAWMRQwEgYDVQQDEwtSb290IEFnZW5jeTAeFw0wMzA3MDgxODQ4MTBaFw0zOTEyMzEyMzU5NTlaMB8xHTAbBgNVBAMTFFdTRTJRdWlja1N0YXJ0U2VydmVyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLkqglArInukRlDwXbcjN3zxfsjeaLd+IvfyD5o35pUjpTkPwPXmApScr8UVQxB5JDRSVlMz1lUQ6CBLFLGIAQOpbPKn2oul3VmKAf9nRQf9PLU+biWozZXkhebIya43D75r5+5NUq1RbQiCC4qIobRqUdg6adujBY333wJy4YgwIDAQABo0swSTBHBgNVHQEEQDA+gBAS5AktBh0dTwCNYSHcFmRjoRgwFjEUMBIGA1UEAxMLUm9vdCBBZ2VuY3mCEAY3bACqAGSKEc+41KpcNfQwDQYJKoZIhvcNAQEEBQADQQAGSGNKz1gZqbXN8JYl0PQM7ngkHfW1mQ88NRYADmoHw5A/rUZDHAPs5HLSn3i5iXlRwT91v3SU6iuaAid+Mwyq</o:BinarySecurityToken>
<Signature Id="_1" 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#hmac-sha1" />
<Reference URI="#_3">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>kfHv+ox3q9X1TBrGhqfRkhUwH5o=</DigestValue>
</Reference>
<Reference URI="#uuid-162e5c78-b008-4cec-ba06-2640994e2742-2">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>DNg0TFHjwKTUosNVojwllIUg+eI=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>AphxxSDF76xcRfix4jXTDyjM7oM=</SignatureValue>
<KeyInfo>
<o:SecurityTokenReference>
<o:Reference URI="#_0" />
</o:SecurityTokenReference>
</KeyInfo>
</Signature>
<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="#_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>2T3przKs8EVfz5D4vHC2AjJfqO8=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>TpZHfGBDYbLKGrgFbssFC3sOWG/cZaXcIIhuurKTs7Bk7vtpLIskaspPaGsz34hhtb06kgmFW5rDRmnQ5rCyq0DxpmwIPH8aNgm2aNFjsiktsEcavUkphEKW+vOMPAuYPVhZyfdMVJukSkz4PhkqY+zWvCTW5aCo7Q4iYR4XTmI=</SignatureValue>
<KeyInfo>
<o:SecurityTokenReference>
<o:Reference URI="#uuid-5721d2b5-ca82-4ddb-9f1f-33e0d77c8492-1" />
</o:SecurityTokenReference>
</KeyInfo>
</Signature>
</o:Security>
</s:Header>
<s:Body u:Id="_3">
<EchoString xmlns="http://tempuri.org/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<s>1</s>
</EchoString>
</s:Body>
</s:Envelope>
|
For all things interop wssecurity10 is your friend and wssecurity10 is
the enemy. keep your friends close! Make sure the messageSecurityVersion
attribute has a value that starts with wssecurity10:
1
2
|
<security authenticationMode="MutualCertificate"
messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10" />
|
Confusion 10: You get this error :
Identity
check failed for outgoing message. The expected DNS identity of the
remote endpoint was 'localhost' but the remote endpoint provided DNS
claim 'WSE2QuickStartServer'. If this is a legitimate remote endpoint,
you can fix the problem by explicitly specifying DNS identity
'WSE2QuickStartServer' as the Identity property of EndpointAddress when
creating channel proxy.
You fell for the oldest trick in the book! Just do
exactly what the error tells you to do . Yes, it's ok...
Confusion 11: You get a good response from the server but the proxy throws this error:
No Timestamp is available in security header to do replay detection
or this one:
The security header element ‘timestamp’ with ‘Timestamp-xxxx’ id must be signed.
These may happen when you send to the server a signed timestamp so wcf
expects to get one back AND to have it signed. So either you do not get
one back or it is not signed. For start try to set the includeTimestamp
property on the "security" binding element to false. But this will not
work if the server actually requires a timestamp. If it requires one but
unsigned then write a
custom encoder
to you proxy and manually generate and push the timestamp header to the
request. If the server requires a signed timestamp then your only hope
is to set allow unsecured response to true (.net 4 only):
1
|
<security ... enableUnsecuredResponse="true" ... />
|
AND to strip out ANY remains of the "security" tag from the response (not just the timestamp) using a
custom encoder.
If WCF will see the security tag then it will be very defensive and try
to validate it. Of course if the security tag which you removed
contains some signature this means you will not be able to validate it,
which is a shame. I'm not familiar with any better workaround at this
moment, so I'm investigating a few directions.
Confusion 12: Ssl is used, and you try certificateOverTransport
instead of mutualCertificate authentication mode on your custom binding.
You may get away with the request, since it is similar, but once the
response come back you may experience:
Cannot
find a token authenticator for the
'System.IdentityModel.Tokens.X509SecurityToken' token type. Tokens of
that type cannot be accepted according to current security settings.
What's going on here? certificateOverTransport assumes the client
authenticates with a message level certificate, but the server
authenticates with its transport ssl certificate. However a more common
use case is that the server also authenticates with a message level
certificate, in addition to its transport one. You could identify such
scenario by seeing a signature element in the server response. This
means you need a mutualCertificate authentication mode together with an
https transport binding element:
1
2
3
4
5
6
7
8
9
|
<customBinding>
<binding name="NewBinding0">
<textMessageEncoding />
<security enableUnsecuredResponse="true" authenticationMode="MutualCertificate" messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
<secureConversationBootstrap />
</security>
<httpsTransport />
</binding>
</customBinding>
|
Summary
When Wcf consumes third party services, the most common
authenticationMode would be "mutualCertifiate". Make sure you tried all
combinations of this setting before trying other settings. Of course if
you are in a situation where mutualCertificate clearly does not apply
(e.g. username authentication) then this is not relevant for you. But
even when usernames are used they may still be in combination with a
client certificate, in which case it would still make sense to
SecurityBindingElement.CreateMutualCertificateBindingElement() for
bootstrap and add the username as a supporting token.
No comments:
Post a Comment