Configuring wcf soap 1.2 service - web-services

I am working on implementation of service that should accept SOAP 1.2 request with with HTNG 2.1 header, WS-Addressing (to communicate message IDs between systems and address destinations) and WS-Security (user authentication only).
I have completed the whole business logic of processing payload message and generating proper response but I have a real trouble configuring my service to predefined request.
Here it is:
<Envelope xmlns="http://www.w3.org/2003/05/soap-envelope">
<soap2:Header xmlns:soap2="http://www.w3.org/2003/05/soap-envelope"
xmlns:htng="http://htng.org/1.3/Header/"
xmlns:wsa="http://www.w3.org/2005/08/addressing"
xmlns:wss="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:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:htnga="http://htng.org/PWSWG/2007/02/AsyncHeaders"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<wsa:Action>http://MyHost/MyService_SubmitRequest</wsa:Action>
<wsa:ReplyTo>
<wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
</wsa:ReplyTo>
<htnga:ReplyTo>
<wsa:Address>HTTPS://ResponseHost/Response.SVC</wsa:Address>
</htnga:ReplyTo>
<wss:Security mustUnderstand="1">
<wss:UsernameToken>
<wss:Username>string</wss:Username>
<wss:Password>string</wss:Password>
</wss:UsernameToken>
</wss:Security>
<wsa:MessageID>df559145-78a4-4c85-a264-bf99bbf8df9e</wsa:MessageID>
<htnga:CorrelationID>df559145-78a4-4c85-a264-bf99bbf8df9e</htnga:CorrelationID>
<wsa:To>https://pms.url</wsa:To>
</soap2:Header>
<Body>
<!-- Payload -->
</Body>
</Envelope>
I want configuration in config file, not in code and I have tried all configuration options I could find in various posts without any success.
I am aware that I am probably missing some basics about WCF that I can't spot right now so at least a point in right direction will help.

As far as I know, the MesaageID/ReplyTo header could be added in the SOAP header by setting up the message version.
How to add MessageID in the soap headers of WCF request and response?
And UsernameToken could be added by authenticating the client with username/password pattern.
<customBinding>
<binding name="mybinding">
<textMessageEncoding messageVersion="Soap12WSAddressing10">
</textMessageEncoding>
<security authenticationMode="UserNameOverTransport" includeTimestamp="false" >
</security>
<httpsTransport></httpsTransport>
</binding>
</customBinding>
Result.
Correct way communicate WSSE Usernametoken for SOAP webservice
I don’t know how to add HGNGA:CorrelationID header to the SOAP header, It might relate to the WCF tracing.
Feel free to let me know if there is anything I can help with.

Related

Duplicating a same SOAP webservice in Camel

A SOAP webservice is been exposed by a system. I have got a wsdl file of the webservice. Im able to send request and get response from soap ui. I want to duplicate this wsdl SOAP webservice in my camel routes deployed in servicemix, thereby making my ESB expose a similar webservice as the system's webservice. THis way many systems access this webservice to contact the system.
How do i duplicate a webservice using wsdl file of the system??
To duplicate webservice, exposed by a system, you can use http proxy route, based on jetty:
<route id="ServiceProxy">
<from uri="jetty:http://0.0.0.0:8186/service/?disableStreamCache=true&matchOnUriPrefix=true&continuationTimeout=900000&httpClient.timeout=120000"/>
<to uri="jetty:http://{{app-server.host}}:{{app-server.http.port}}/service/?bridgeEndpoint=true&throwExceptionOnFailure=false&continuationTimeout=120000&httpClient.timeout=900000"/>
</route>
You can write the same route on JavaDSL.
Found solution - Concept is cxf-proxying
Having a wsdl of the system, create a similar wsdl with the Endpoints defined according to the localhost and port number.
Save the wsdl in your local project,
provide the path to wsdl in pom, for converting wsdl to java by mentioning in the cxf-codegen-plugin.
create cxf consumer bean with details of local wsdl file
<cxf:cxfEndpoint id="consumerProxy" address="http://remote:port/service/"
serviceClass="com.remote.service.RemoteService" endpointName="c:RemoteService"
serviceName="c:RemoteService" xmlns:c="http://remote/namespace/">
<cxf:properties>
<entry key="dataFormat" value="MESSAGE" />
</cxf:properties>
</cxf:cxfEndpoint>
create cxf producer bean with details of remote wsdl file
<cxf:cxfEndpoint id="producerRemote" address="http://localhost:9001/service/"
serviceClass="com.remote.service.RemoteService" endpointName="c:RemoteService"
serviceName="c:RemoteService" xmlns:c="http://remote/namespace/">
<cxf:properties>
<entry key="dataFormat" value="MESSAGE" />
</cxf:properties>
</cxf:cxfEndpoint>
The proxy routes can be like below
from(cxfEndpoint("consumerProxy"))
.to(cxfEndpoint("producerRemote"));
Sending a request to localhost will be consumed by cxf endpoint - consumerProxy and sent to the cxf endpoint - producerRemote.
The response is sent back the reverse way.

WSO2 requests from BPS (BPEL) to ESB with missing soapAction header

I am using WSO2 BPS 3.2.0, WSO2 Application server 5.2.1 and WSO2 Identity server 5.0.0.
I make BPS process which communicate with basic authentication secured ESB proxy services through HTTPS. Process have problem with soap action. Requests ends with Fault response:
<message><fault><faultcode xmlns:soapenv="http://schemas.xmlsoap.org/soa...">axis2ns10:Client</faultcode><faultstring xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">The endpoint reference (EPR) for the Operation not found is /services/RepositoryService and the WSA Action = . If this EPR was previously reachable, please contact the server administrator.</faultstring></fault></message>
I use unified-endpoints(UEPs) from this blog.
<wsa:EndpointReference
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3schools.com uep_schema.xsd"
xmlns:wsa="http://www.w3.org/2005/08/addressing"
xmlns:wsdl11="http://schemas.xmlsoap.org/wsdl/">
<wsa:Action>http://docs.oasis-open.org/ns/cmis/ws/200908/RepositoryServicePort/getRepositoriesRequest</wsa:Action>
<wsa:Metadata>
<id>SInvokeEPR</id>
<transport type="http">
<authorization-username>user</authorization-username>
<authorization-password>pass</authorization-password>
</transport>
</wsa:Metadata>
</wsa:EndpointReference>
I found some possibility with assign
<bpel:literal>
<wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">http://docs.oasis-open.org/ns/cmis/ws/200908/RepositoryServicePort/getRepositoriesRequest</wsa:Action>
</bpel:literal>
to output variable property
<bpel:to variable="RepositoryServicePLRequest" header="Action"></bpel:to>
But it doesn't work. But I found that it starts working when I enable SOAP Message Tracer in ESB. Why?
You can use fix from this post
Add parameter
<parameter name="disableOperationValidation" locked="false">true</parameter>
to your proxy conf in WSO2 ESB
I had been around this problem for the last two days. And I have several points to your question and your answer. To let you know I don´t have an ESB so I have the same problem but I can not use this approach to solve it.
First checking your first link you see there is no wsa:Action so you need to specify wsa:address instead.
The second problem is your SOAPACTION is not set. If you use SOAP 1.1 you need this header so BPS set it as "" for you but most of servers need the real action. To solve this you need to enableAddressing in your epr file. It is a bit confusing because it adds the proper ws-addressing information but it controls SOAPACTION which is not related to it.
So to solve the problem just put your epr like this:
<wsa:EndpointReference
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3schools.com uep_schema.xsd"
xmlns:wsa="http://www.w3.org/2005/08/addressing"
xmlns:wsdl11="http://schemas.xmlsoap.org/wsdl/">
**<wsa:Address>http://docs.oasis-open.org/ns/cmis/ws/200908/RepositoryServicePort</wsa:Address>**
<wsa:Metadata>
<id>SInvokeEPR</id>
<transport type="http">
<authorization-username>user</authorization-username>
<authorization-password>pass</authorization-password>
</transport>
**<qos>
<enableAddressing version="final" separateListener="true"/>
</qos>**

cxf webservice over jms, how to get wsdl

I have a webservice configured like this.
<jaxws:endpoint
id="helloWorld"
xmlns:hello="http://service.test.com/"
serviceName="hello:MyServiceImplService"
endpointName="hello:MyServiceImplPort" address="jms://"
implementor="com.test.service.MyServiceImpl" >
<jaxws:features>
<bean class="org.apache.cxf.feature.LoggingFeature" />
<bean class="org.apache.cxf.transport.jms.JMSConfigFeature">
<property name="jmsConfig" ref="jmsConfig"/>
</bean>
</jaxws:features>
</jaxws:endpoint>`
I want to have the cxf generate the wsdl for me. when the service is http, I can access the wsdl from a url like this http://localhost:8080/server/hello?wsdl, after I change the transport to jms, how do I access the wsdl? what's the jms message I need to send to get the wsdl. or I have to write the wsdl first and expose it through a regular http request. I am asking this because the client need to know the wsdl to get all the type and binding information to generate class. client should already know how to connect the queue.
You can use commandline java2ws tool (see http://cxf.apache.org/docs/java-to-ws.html) passing it your implementation class. There is also a sample invocation from Ant script. It will generate WSDL which your client can use to generate client code.

How to add <soap:Header> tag? WSDL not appearing with these info

I need to add to my message something like this:
<soap:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soap:mustUnderstand="1">
<wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="unt_Z1k4LnxEmBzzKuPP">
<wsse:Username>user</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:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">iNs+LF1iwwPU2AMer8uU6NKY9tfzgYqMTaP3mIEgoK0=</wsse:Nonce>
<wsu:Created>2012-04-22T11:57:30Z</wsu:Created>
</wsse:UsernameToken>
<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsu:Created>2012-04-22T11:57:30Z</wsu:Created>
<wsu:Expires>2012-04-22T11:58:30Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
</soap:Header>
I'm calling a web service which return a 500 error response which basically means it cannot authenticate I guess cause I'm missing these information from the message, even I have an authentication header on the message. Can this be happening?
How can I add the WS-Security header in the message and add all these info in code?
I added the service using Add Web Reference in Visual Studio.
Thank you.
The most elegant solution is an obsolete solution regarding making the class llibrary that I use to make calls from .NET 3.5 to .NET 2.0, installing WSE 3.0, hacking into some VS config files to make the add-in work and enabling the class library project as WSE Enabled project.
Update Web Reference makes two proxy classes (e.g. Myservice and MyServiceWse),. One inherits from SoapHttpClient, which is the default for WCF proxy generation and latest inherits from WebServicesClientProtocol.
The latest is what you need to call old ASMX Web Services using the WS-Security headers.
The rest is so easy:
MyServiceWse client = new MyServiceWse();
UsernameToken token = new UsernameToken(userName, password, PasswordOption.SendPlainText); // or what service specs rquired, other than plaintext.
client.RequestSoapContext.Security.Tokens.Add(token);
client.RequestSoapContext.Security.Timestamp.TtlInSeconds = 60;
client.YourMethod();
So simple for an obsolete API which Microsoft is not included after VS 2005 and you need to play with Stream and string manipulation catching the message before serialize, after serialization, using extensions and stuff...
If you have a solution for this using Add Reference and not the old Add Web Reference and WSE to make a simple call with WS-Security header, UsernameToken, TimeStamp Created, Expired etc.
Please let me know.
P.S. Find the solution over this question and answer with some useful links.
Consuming non-asmx SOAP 1.1 Web Service in C# with Header Security

Glassfish, EJB3, SOAP web service and basic authentication

I'm setting up a glassfish server with a single EJB3 as a mocked up backend for a POC. Everything was working fine until I went to add some basic authentication. Just plan text userid and password, nothing sophisticated for this job. I added the following annotations to the EJB:
#WebService(name = "Banking", serviceName = "Banking", targetNamespace = BANKING_NAMESPACE)
#DeclareRoles("user")
#Stateless
public class Banking {
...
#RolesAllowed("user")
#SOAPBinding(parameterStyle = ParameterStyle.BARE)
#WebMethod(action = BANKING_NAMESPACE + "/logon", operationName = "logon")
#WebResult(targetNamespace = XmlStrings.BANKING_MODEL_NAMESPACE)
public LogonResponse logon(#WebParam(targetNamespace = XmlStrings.BANKING_MODEL_NAMESPACE) Logon request) throws WebServiceException {
...
}
}
According to what I've read of EJB3 spec, this is pretty common for doing a SOAP web service.
However when I send this xml:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:mod="http://www.dhcbank.com/banking/model">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-79" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>fred</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">fred</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<mod:logon/>
</soapenv:Body>
</soapenv:Envelope>
I get the following error back as a SOAP fault:
java.lang.Exception: Client not authorized for invocation of public com.dhcbank.www.banking.schema.LogonResponse com.dhcbank.www.banking.Banking.logon(com.dhcbank.www.banking.schema.Logon) throws javax.xml.ws.WebServiceException
And in the glassfish log:
[#|2010-10-10T12:49:27.497+1100|INFO|glassfish3.0.1|javax.enterprise.system.core.security|_ThreadID=41;_ThreadName=http-thread-pool-8080-(2);|JACC Policy Provider: Failed Permission Check, context(BankingEAR/Banking_war_internal)- permission((javax.security.jacc.EJBMethodPermission Banking logon,ServiceEndpoint,com.dhcbank.www.banking.schema.Logon))|#]
In the glassfish admin screens I added a user called fred with a fred password and assigned it to a groups called user. But that didn't work.
I did some more reading which suggested that I create a sun-ejb-jar.xml file and add it to the ear file. So I created it with this content:
<sun-ejb-jar>
<enterprise-beans>
<ejb>
<ejb-name>Banking</ejb-name>
<webservice-endpoint>
<port-component-name>Banking</port-component-name>
<login-config>
<auth-method>BASIC</auth-method>
<realm>file</realm>
</login-config>
</webservice-endpoint>
</ejb>
</enterprise-beans>
</sun-ejb-jar>
This is as near as I can tell, correct. However I could not find anything that told me what the values of the port-component-name element should be. So I don't know if I've got it right.
Security does still not appear to be working and I cannot figure out why. Does anyone have any experience with this and can point me at what I've got wrong or not done?
I'm assuming your declared role "user" is the same role name in your file realm? if not provide this mapping in your descriptor:
<sun-ejb-jar>
<security-role-mapping>
<role-name>user</role-name>
<group-name>filerealm-group-name</group-name>
</security-role-mapping>
...
I don't think that you're currently creating the appropriate HTTP header for Basic Authentication. I'm not sure how you create the SOAP request but if you're using a JAX-WS client, the JAX-WS FAQ documents the following:
Q. How do I do basic authentication in JAX-WS?
You can do the following:
HelloService service = new HelloService();
Hello proxy = (service.getHelloPort());
((BindingProvider)proxy).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "userfoo");
((BindingProvider)proxy).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "passbar");
USERNAME_PROPERTY, PASSWORD_PROPERTY
are used primarily for service
requests. I think when you instantiate
Service, it fetches WSDL and the
server is returning 401. You could try
any one of the following solutions.
Use java.net.Authenticator class in your client application.
Provide a local access to the WSDL using catalog. There is a catalog
sample in the jax-ws distribution.
Configure web.xml to allow GET requests without authentication
And unless I'm wrong, the usernametoken would fit if the webservice expects the authentication in the SOAP header, which is not the case according to your description.
In other words, for me, you're currently not sending the credentials for the BASIC auth.
See also
Example: Basic Authentication with JAX-WS
SSL and HTTP BASIC authentication with Glassfish and JAX-WS (more complex scenario)