how do i make wcf client that'll talk to this wse service (with included policy)
I’m using a service that is using username token authentication and it’s built in wse 3.0.
http://msdn2.microsoft.com/en-US/library/aa480575.aspx
I am trying to interop with it via wcf like so:
http://msdn2.microsoft.com/en-us/library/ms730299.aspx
Code Snippetthe vendor who makes the service has given me the following policy file
<policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy">
<extensions>
<extension name="usernameOverTransportSecurity" type="Microsoft.Web.Services3.Design.UsernameOverTransportAssertion, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<extension name="requireActionHeader" type="Microsoft.Web.Services3.Design.RequireActionHeaderAssertion, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</< SPAN>extensions>
<policy name="InsertNameHere">
<usernameOverTransportSecurity />
<requireActionHeader />
</< SPAN>policy>
</< SPAN>policies>
However, the services are NOT on SSL they’re hosted on basic HTTP.
I wrote the following client to try to talk to the service
Code SnippetConsole.Write("Logging in...");
//Configure an anon binding so we can log in
WseHttpBinding binding = new WseHttpBinding();
binding.LoadPolicy("wse3policyCache.config", "InsertNameHere");
LoginServiceSoapClient loginClient =
new LoginServiceSoapClient(binding,
new EndpointAddress("HTTP://myserver/myLoginService.asmx") );
Guid guid = loginClient.LogIn("username", "myP4ssw0rd",true);
Console.WriteLine("Logged in!");
Console.WriteLine(" (press any key to exit) ");
Console.ReadKey();
Now I’m stuck because it says that http isn’t valid, but if I use https it can’t find the certificate, because there isn’t one.
Thanks,
the vendor has a wse client that talks to this service just fine but they don't know anything about wcf yet, but we only use wcf and arent familiar with wse.
All Replies
If I understand this scenario correctly, you are trying to write a WCF client which talks to a WSE service which exposes "usernameOverTransport" in its policy, but its not using transport security.
Have you tried converting the generated Wse binding on the WCF client side, converting it to a custom binding, and replacing the transport security layer with a nonsecure HttpTransportBindingElement?
YES! that is correct, this service utilizes usernameOverTransport but has no transport security (if that's bad i'd like to know why so i can tell the vendor to fix it). However, i do not know how to do what you're suggesting to try. I think we already have a 'custom binding' created from the example in wse samples at http://msdn2.microsoft.com/en-us/library/ms752257.aspx .
looks like this:
Code Snippetnamespace
Srg.Wse.Interop{
public enum WseSecurityAssertion{
UsernameOverTransport = 0,
MutualCertificate10 = 1,
UsernameForCertificate = 2,
AnonymousForCertificate = 3,
MutualCertificate11 = 4,
Kerberos = 5
}
public class WseHttpBinding :Binding{
public WseHttpBinding() { } public override BindingElementCollection CreateBindingElements(){
//SecurityBindingElement sbe = bec.Find<SecurityBindingElement>(); BindingElementCollection bec = new BindingElementCollection(); // By default http transport is used SecurityBindingElement securityBinding; BindingElement transport; switch (assertion){
case WseSecurityAssertion.UsernameOverTransport:transport =
new HttpsTransportBindingElement();securityBinding = (
TransportSecurityBindingElement)SecurityBindingElement.CreateUserNameOverTransportBindingElement(); if (establishSecurityContext == true) throw new InvalidOperationException("Secure Conversation is not supported for this Security Assertion Type"); if (requireSignatureConfirmation == true) throw new InvalidOperationException("Signature Confirmation is not supported for this Security Assertion Type"); break; case WseSecurityAssertion.MutualCertificate10:transport =
new HttpTransportBindingElement();securityBinding =
SecurityBindingElement.CreateMutualCertificateBindingElement(MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10); if (requireSignatureConfirmation == true) throw new InvalidOperationException("Signature Confirmation is not supported for this Security Assertion Type");((
AsymmetricSecurityBindingElement)securityBinding).MessageProtectionOrder = messageProtectionOrder; break; case WseSecurityAssertion.UsernameForCertificate:transport =
new HttpTransportBindingElement();securityBinding = (
SymmetricSecurityBindingElement)SecurityBindingElement.CreateUserNameForCertificateBindingElement(); // We want signatureconfirmation on the bootstrap process // either for the application messages or for the RST/RSTR((
SymmetricSecurityBindingElement)securityBinding).RequireSignatureConfirmation = requireSignatureConfirmation;((
SymmetricSecurityBindingElement)securityBinding).MessageProtectionOrder = messageProtectionOrder; break; case WseSecurityAssertion.AnonymousForCertificate:transport =
new HttpTransportBindingElement();securityBinding = (
SymmetricSecurityBindingElement)SecurityBindingElement.CreateAnonymousForCertificateBindingElement();((
SymmetricSecurityBindingElement)securityBinding).RequireSignatureConfirmation = requireSignatureConfirmation;((
SymmetricSecurityBindingElement)securityBinding).MessageProtectionOrder = messageProtectionOrder; break; case WseSecurityAssertion.MutualCertificate11:transport =
new HttpTransportBindingElement();securityBinding =
SecurityBindingElement.CreateMutualCertificateBindingElement(MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11);((
SymmetricSecurityBindingElement)securityBinding).RequireSignatureConfirmation = requireSignatureConfirmation;((
SymmetricSecurityBindingElement)securityBinding).MessageProtectionOrder = messageProtectionOrder; break; case WseSecurityAssertion.Kerberos:transport =
new HttpTransportBindingElement();securityBinding = (
SymmetricSecurityBindingElement)SecurityBindingElement.CreateKerberosBindingElement();((
SymmetricSecurityBindingElement)securityBinding).RequireSignatureConfirmation = requireSignatureConfirmation;((
SymmetricSecurityBindingElement)securityBinding).MessageProtectionOrder = messageProtectionOrder; break; default: throw new NotSupportedException("This supplied Wse security assertion is not supported");}
//Set defaults for the security bindingsecurityBinding.IncludeTimestamp =
true; // Derived Keys // set the preference for derived keys before creating SecureConversationBindingElementsecurityBinding.SetKeyDerivation(requireDerivedKeys);
//Secure Conversation if (establishSecurityContext == true){
SymmetricSecurityBindingElement secureconversation =(
SymmetricSecurityBindingElement)SymmetricSecurityBindingElement.CreateSecureConversationBindingElement(securityBinding,
false); // This is the default //secureconversation.DefaultProtectionLevel = ProtectionLevel.EncryptAndSign; //Set defaults for the secure conversation bindingsecureconversation.DefaultAlgorithmSuite =
SecurityAlgorithmSuite.Basic256; // We do not want signature confirmation on the application level messages // when secure conversation is enabled.secureconversation.RequireSignatureConfirmation =
false;secureconversation.MessageProtectionOrder = messageProtectionOrder;
secureconversation.SetKeyDerivation(requireDerivedKeys);
securityBinding = secureconversation;
}
// Add the security binding to the binding collectionbec.Add(securityBinding);
// Add the message encoder. TextMessageEncodingBindingElement textelement = new TextMessageEncodingBindingElement();textelement.MessageVersion =
MessageVersion.Soap11WSAddressingAugust2004; //These are the defaults required for WSE //textelement.MessageVersion = MessageVersion.Soap11Addressing1; //textelement.WriteEncoding = System.Text.Encoding.UTF8;bec.Add(textelement);
// Add the transportbec.Add(transport);
// return the binding elements return bec;}
// Finds the named WSE 3.0 Policy and initialize the WseHttpBinding; public void LoadPolicy(String filename, String policyName){
bool readPolicy = false; XmlReader reader = XmlReader.Create(filename);reader.MoveToContent();
if (!reader.ReadToDescendant("policy", "http://schemas.microsoft.com/wse/2005/06/policy")) throw new InvalidOperationException("The reader does not contain any Policy element. Check the policy file if it contains any policy."); do{
if (reader["name"] == policyName){
reader.Read();
reader.MoveToContent();
switch (reader.Name){
case "usernameForCertificateSecurity":SecurityAssertion =
WseSecurityAssertion.UsernameForCertificate;PolicyProperties(reader.ReadSubtree());
break; case "usernameOverTransportSecurity":SecurityAssertion =
WseSecurityAssertion.UsernameOverTransport;PolicyProperties(reader.ReadSubtree());
break; case "mutualCertificate10Security":SecurityAssertion =
WseSecurityAssertion.MutualCertificate10;PolicyProperties(reader.ReadSubtree());
break; case "mutualCertificate11Security":SecurityAssertion =
WseSecurityAssertion.MutualCertificate11;PolicyProperties(reader.ReadSubtree());
break; case "anonymousForCertificateSecurity":SecurityAssertion =
WseSecurityAssertion.AnonymousForCertificate;PolicyProperties(reader.ReadSubtree());
break; case "kerberosSecurity":SecurityAssertion =
WseSecurityAssertion.Kerberos;PolicyProperties(reader.ReadSubtree());
break; // not used. case "authorization": case "requireSoapHeader": case "requireActionHeader": default: throw new NotSupportedException("The given policy contains unrecognized or unsupported security element.");}
readPolicy =
true; break;}
}
while (reader.ReadToNextSibling("policy", "http://schemas.microsoft.com/wse/2005/06/policy")); if (!readPolicy) throw new InvalidOperationException("The given policy name is not present in the given reader.");}
void PolicyProperties(XmlReader reader){
reader.Read();
//Set the Security Assertion XML attributes onto the binding properties while (reader.MoveToNextAttribute()){
if (reader.Name == "establishSecurityContext")EstablishSecurityContext = reader.ReadContentAsBoolean();
if (reader.Name == "requireSignatureConfirmation")RequireSignatureConfirmation = reader.ReadContentAsBoolean();
if (reader.Name == "requireDerivedKeys")RequireDerivedKeys = reader.ReadContentAsBoolean();
if (reader.Name == "messageProtectionOrder"){
String protectionOrder = reader.Value; switch (protectionOrder){
case "SignBeforeEncrypt":MessageProtectionOrder =
MessageProtectionOrder.SignBeforeEncrypt; break; case "EncryptBeforeSign":MessageProtectionOrder =
MessageProtectionOrder.EncryptBeforeSign; break; case "SignBeforeEncryptAndEncryptSignature":MessageProtectionOrder =
MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature; break;}
}
}
}
public override string Scheme{
get { return "http"; }}
private WseSecurityAssertion assertion; public WseSecurityAssertion SecurityAssertion{
get { return assertion; } set { assertion = value; }}
private bool requireDerivedKeys; public bool RequireDerivedKeys{
get { return requireDerivedKeys; } set { requireDerivedKeys = value; }}
private bool establishSecurityContext; public bool EstablishSecurityContext{
get { return establishSecurityContext; } set { establishSecurityContext = value; }}
private bool requireSignatureConfirmation; public bool RequireSignatureConfirmation{
get { return requireSignatureConfirmation; } set { requireSignatureConfirmation = value; }}
private MessageProtectionOrder messageProtectionOrder; public MessageProtectionOrder MessageProtectionOrder{
get { return messageProtectionOrder; } set { messageProtectionOrder = value; }}
}
}
How would i go about replacing the transport security layer?
hah ok, after actually reading the code i pasted, i see transport = httpsBindingElement()... i just need to change that to httpBinding element, right?
i did this:
Code Snippetcase WseSecurityAssertion.UsernameOverTransport:
transport = new HttpTransportBindingElement();
securityBinding = (TransportSecurityBindingElement)SecurityBindingElement.CreateUserNameOverTransportBindingElement();
if (establishSecurityContext == true)
throw new InvalidOperationException("Secure Conversation is not supported for this Security Assertion Type");
if (requireSignatureConfirmation == true)
throw new InvalidOperationException("Signature Confirmation is not supported for this Security Assertion Type");
break;
but now i get:
Code SnippetThe 'WseHttpBinding'.'http://tempuri.org/' binding for the '******SERVICE NAME***'.'*****URI**************' contract is configured with an authentication mode that requires transport level integrity and confidentiality. However the transport cannot provide integrity and confidentiality.
we aren't using ssl and the vendor's client works with their services fine... if you know what i'm missing please let me know. Thanks
Hi,
Shiung Yong - MSFT wrote: If I understand this scenario correctly, you are trying to write a WCF client which talks to a WSE service which exposes "usernameOverTransport" in its policy, but its not using transport security.
Have you tried converting the generated Wse binding on the WCF client side, converting it to a custom binding, and replacing the transport security layer with a nonsecure HttpTransportBindingElement?
interesting, I might be overlooking the simple solution here, but the only way I can imagine this is if you implemented ISecurityCapabilites and then return false on all the Supportxxxx methods ?, return that interface in the GetProperty<T> in his own derived HttpsTransportBindingElement class! (looking at JDPechams code there).
is that what you saying here Yong ?
Allan
- There is a work around for this.
Use ClearUserPassBinding (search on google.)
Its a custom binding code available on internet.
Dont forget to set the Proper MessageVersion and includeTimestamp= false
u also need to pass the credentials as well
serviceCilentPortType.ClientCredentials.UserName.UserName =
"username";
serviceClientPortType.ClientCredentials.UserName.Password =
"password";


