Wcf service server - authentication with usernametoken - c#

we are trying to create server from given demo wsdl. Wsdl does not contains security but we need implement usernametoken where request header looks like this:
<soap:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:env="http://www.w3.org/2003/05/soap-envelope" env:mustUnderstand="true">
<wsse:UsernameToken wsu:Id="UsernameToken-7dd435a5-b8bb-4388-bba3-f77512a14351">
<wsse:Username>CES</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">e8I23Z92JGgSREAb=</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">v21JzUcrKZiZ7MC==</wsse:Nonce>
<wsu:Created>2017-10-13T13:00:02.221Z</wsu:Created>
</wsse:UsernameToken>
<wsse:SecurityTokenReference>
<wsse:Embedded wsse:ValueType="http://www.asktirweb.org/security/authentication/username" wsu:Id="alex"/>
</wsse:SecurityTokenReference>
</wsse:Security>
<Action xmlns="http://www.w3.org/2005/08/addressing">http://www.asktirweb.org/services/TIRAccountingService-1/sendInvoice</Action>
<MessageID xmlns="http://www.w3.org/2005/08/addressing">urn:uuid:321a0dff-61a8-4eae-8934-7f06e8d87648</MessageID>
<To xmlns="http://www.w3.org/2005/08/addressing">http://wiesbaden:8040/askdemo/hs/AskTirWebDemo/WsSecurityRequests</To>
<ReplyTo xmlns="http://www.w3.org/2005/08/addressing">
<Address>http://www.w3.org/2005/08/addressing/anonymous</Address>
</ReplyTo>
</soap:Header>
Any suggestions ?

Please try the below custom binding, it might be useful to you.
<customBinding>
<binding name="mybinding">
<textMessageEncoding messageVersion="Soap12WSAddressing10">
</textMessageEncoding>
<security authenticationMode="UserNameOverTransport" includeTimestamp="false" >
</security>
<httpsTransport></httpsTransport>
</binding>
</customBinding>
And the request body captured by Fiddle.
Besides, can we use the WSDL file to generate the client configuration, which has contained the essential binding type and security authentication mode? Like the below Tools.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/servicemodel-metadata-utility-tool-svcutil-exe
By default, it is a built-in tool in VS Developer Command Prompts.
svcutil https://vabqia969vm:21011
It will generate the output.config in the current directory, it contains the binding configuration to be used in WCF.
Feel free to let me know if there is anything I can help with.

Related

How do I remove WSS-Password Type requirement in WCF Service?

I built a WCF service with basicHttpBinding with the binding configuration as shown below
<basicHttpBinding>
<binding name="basicHttpBinding">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" proxyCredentialType="None"/>
<message clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpBinding>
When I host this service on IIS add this in SoapUI for testing, it forces me to set WSS-Password Type as PasswordText.
The consumer of this service uses some tool to access service methods claim, they can't supply password type in their tool or language. (out of topic).
So, I have tried various ways setting security mode as None, Message but nothing worked.
I need to receive user name and password so non-authenticated requests are not the requirements here.
<behavior name="customBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="CustomServices.Library.UserValidator, CustomServices"/>
</serviceCredentials>
</behavior>
How do I host this service to accept user name and password but not password-type as a requirement?
SOAP UI properties seem to simply construct the same SOAP elements which you can write by hand. For instance, after adding a header my whole test message would look like this:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-12" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>john1</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<tem:GetData>
<tem:value>123</tem:value>
</tem:GetData>
</soapenv:Body>
</soapenv:Envelope>
The Security header passes all the user credentials in the above example.
I presume that it's a basic functionality to send messages in the SOAP format when dealing with WCF-services and your client can easily tap into it, can't they?

How to remove Soap Security header

I'm currently trying to consume a SOAP 1.2 web service using a WCF client. Problem is, whenever I make a request a MessageSecurityException with the following inner message is thrown:
SOAP header Security was not understood
From what I can tell, the WS does not understand the Security header, which is currently marked as MustUnderstand="true".
How can I change MustUnderstandto false / remove the Security header?
Below is the binding I'm using right now:
<customBinding>
<binding name="CteRecepcaoSoap12">
<textMessageEncoding messageVersion="Soap12" />
<security authenticationMode="CertificateOverTransport"/>
<httpsTransport requireClientCertificate="true"/>
</binding>
</customBinding>

How to add custom security binding credentials to a web service reference?

I'm new to Service Reference stuff so I might need simple explanation.
I got a WSDL:
https://test.servicebench.com/servicebenchv5/services/CRMServiceOrderService?wsdl
I added the Service Reference in my project via MVS2013 without any problem.
Here's the autogenerated app.config file :
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<customBinding>
<binding name="CRMServiceOrderBinding">
<textMessageEncoding messageVersion="Soap11" />
<httpsTransport />
</binding>
</customBinding>
</bindings>
<client>
<endpoint
address="https://test.servicebench.com/servicebenchv5/services/CRMServiceOrderService"
binding="customBinding"
bindingConfiguration="CRMServiceOrderBinding"
contract="ServiceBenchReference.CRMServiceOrderPortType"
name="CRMServiceOrderPort" />
</client>
</system.serviceModel>
</configuration>
Now, every requests I try to make to the server replies me : "Unauthorized".
I pretty sure it's because I didn't passed the required credentials in the SOAP request header.
I need to pass it 3 credentials (or info?) : ServiceBenchID, UserID and password.
I've tried using :
CRMServiceOrderPortTypeClient ServiceOrder = new CRMServiceOrderPortTypeClient();
ServiceOrder.ClientCredentials.UserName.UserName = myUserID;
ServiceOrder.ClientCredentials.UserName.password = myPassword;
but it didn't work. I checked the request via Fiddler and I didn't saw the credentials passed in the header.
So here's my question : How can I get these 3 custom credentials information to be passed in the header correctly ? (So I get a response from the server)
After searching a couple more hours, I manage to find a suitable solution !
Thanks to Thorarin for the piece of code,
How can I pass a username/password in the header to a SOAP WCF Service
It seems that having custom bindings in the app.config file is forcing you to add the security elements manually. I don't think its the best way to do it, but its working like this.

WCF Username and Password in SOAP Header

I'm trying to get a WCF client to call a web service with security information provided in the SOAP Header of the request, as follows.
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ah_etas_order="http://types.defra.gov.uk/ahw/eartagging/order"
xmlns:ah_common="http://types.defra.gov.uk/ahw/common/complextypes"
xmlns:ah_assettype="http://types.defra.gov.uk/ahw/asset"
xmlns:ah_ref_data_sets="http://types.defra.gov.uk/ahw/common/referencedatasets"
xmlns:ah_custtype="http://types.defra.gov.uk/ahw/customer"
xmlns:m5="http://types.defra.gov.uk/bs7666"
xmlns:m6="http://www.govtalk.gov.uk/people/bs7666"
xmlns:m7="http://types.defra.gov.uk/ahw/common/derivedtypes"
xmlns:ah_etas_type="http://types.defra.gov.uk/ahw/eartagging">
<SOAP-ENV:Header xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:Security soap:role="system" soap:mustUnderstand="true">
<wsse:UsernameToken>
<wsse:Username>username here</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password here</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</SOAP-ENV:Header>
<SOAP-ENV:Body>...</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I'm using Visual Studio 2012 and .NET 4. The docs say the version of SOAP messaging used for CARA Services is SOAP 1.2.
I've added a service reference with has added a web.config file with an endpoint and the following custom binding.
<customBinding>
<binding name="ProcessOrderBinding">
<textMessageEncoding messageVersion="Soap12" />
<httpTransport />
</binding>
</customBinding>
I've tried lots of different web.config options but can't seem to get the correct soap header. Can anyone point me in the right direction?
Update:
#Yaron, Here is the soap header using your binding. I've added a includeTimestamp=false to remove the timestamp.
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<h:Security xmlns:h="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
<VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">
uIDPoxqYDT0sMwVImscgqVaf7GYAAAAAjin6KftLjkaS2CW99IXxrnWGCjfQnzFFuf4zGaQpeqIACQAA
</VsDebuggerCausalityData>
<o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<o:UsernameToken u:Id="uuid-79885712-d6eb-451c-9483-4df2b68722bd-1">
<o:Username>username here</o:Username>
<o:Password>password here</o:Password>
</o:UsernameToken>
</o:Security>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">...</s:Body>
</s:Envelope>
As you can see it's missing the following before the password.
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">
Use this binding:
<customBinding>
<binding name="NewBinding0">
<textMessageEncoding messageVersion="Soap12" />
<security authenticationMode="UserNameOverTransport">
<secureConversationBootstrap />
</security>
<httpsTransport />
</binding>
</customBinding>
Of course you also need to supply user/pass on the proxy:
proxy.ClientCredentials.Username.Username = "user"
proxy.ClientCredentials.Username.Password = "pass"
All this assumes you also use SSL. If you don't then check out CUB.

C# .NET 4.0 WCF MessageSecurityException, "Security header is empty." when consuming a service

When using WCF and C# in a project I get an exception, MesssageSecurityException, with the message "Security header is empty.". Here follows the response (according to MS Service Trace Viewer):
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://www.w3.org/2005/08/addressing">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="true"></wsse:Security>
<wsa:Action>_WHAT_I_DID_</wsa:Action>
<wsa:RelatesTo>_MSG_ID_OF_REQUEST_</wsa:RelatesTo>
</soapenv:Header>
<soapenv:Body>
_CORRECT_BODY_
</soapenv:Body>
</soapenv:Envelope>
Indeed, the security header is "empty", but it is still correct accprding to the security header definition as far as I can tell.
I've also tried editing the bindings, but that doesn't seem to help as well. I also found a similar problem where enabling EnableUnsecuredResponse would help, but it doesn't here.
Here is the response according to SoapUI:
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:wsa="http://www.w3.org/2005/08/addressing">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="true" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"/>
<wsa:Action>_WHAT_I_DID_</wsa:Action>
<wsa:RelatesTo>_REQ_MSG_ID_</wsa:RelatesTo>
</soapenv:Header>
<soapenv:Body>
_CORRECT_BODY_
</soapenv:Body>
</soapenv:Envelope>
They are almost identical, except for how they close the security header. Which is interesting, but should not raise the exception?
I also found a similar problem where the solution was to create a custom message encoder and strip the entire security header, although this would work it is an extra unneeded step. Is that the only way to do it with .Net and WCF? Can't WCF handle security headers without content?
EDIT:
Clarification of the issue, is writing an encoder which drops the security header the only way to recieve and parse SOAP-messages with empty security headers using WCF?
EDIT2: Adding part of conf:
<binding name="NinjaBinding">
<security allowSerializedSigningTokenOnReply="true" enableUnsecuredResponse="true"
authenticationMode="UserNameOverTransport" requireDerivedKeys="false"
securityHeaderLayout="Lax" includeTimestamp="false" allowInsecureTransport="true"
keyEntropyMode="ClientEntropy"
messageProtectionOrder="SignBeforeEncryptAndEncryptSignature"
messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
requireSecurityContextCancellation="false">
<localServiceSettings detectReplays="false" />
<secureConversationBootstrap _IDENTICAL_TO_ABOVE_
</secureConversationBootstrap>
</security>
<textMessageEncoding />
<httpsTransport />
</binding>
As far as I know, its configure to allow practically everything?
(Now I'm answering my own question since I've been able to elicit some kind of answer)
In short, no you cannot use WCF "out of the box" (ie through *.config) with application servers which provide empty security headers in responses. You have to implement an encoder which modifies messages to a format acceptable by the WCF-framework.
For more information read this blog which contains a quite good walkthrough of the encoder and its applications. This blog (another blog) also provides a code snippet capable of solving my issue, ie modifying the security header.
I wonder why MS and Oracle products never can co-exist peacefully :D

Categories