13 March 2017

Username/Password Authentication with Talend ESB WebService

In this Blog post I'll show you how to use Username/Password authentication with a Talend ESB WebService (based on CXF) running inside a Karaf runtime. First with a UsernameToken inside the SOAP Header and second by using BasicAuthentication.

Prepare your Test Service

1.) Start Talend Studio (6.3.1)

2.) Create a new Service
2.1) Name your Service: EchoService
2.2) Select: Create new Service

3.) Import Schema

4.) Implement Service
4.1) Assign Job to operation
4.2) Select: Create a new Job and Assign it to this Service Operation
4.3) Add tXMLMap to your job
4.4) Import Schema to your input and output mapping from your repository
4.5) Define your mapping

5.) Test your Service
5.1) Run your Service inside Studio
5.2) Send a Test Request (for example with SoapUI) to your service at http://localhost:8090/services/EchoService
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://www.talend.org/service/">
   <soapenv:Header/>
   <soapenv:Body>
      <ser:EchoServiceOperationRequest>
         <in>Hello World!</in>
      </ser:EchoServiceOperationRequest>
   </soapenv:Body>
</soapenv:Envelope>
You should get the following response:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <tns:EchoServiceOperationResponse xmlns:tns="http://www.talend.org/service/">
         <out>Hello World!</out>
      </tns:EchoServiceOperationResponse>
   </soap:Body>
</soap:Envelope>

UsernameToken Authentication

1.) Active Username /Passwort ESB Runtime Option
2.) Export Service to Runtime
3.) Start Runtime
C:\Talend\6.3.1\runtime\bin\trun.bat
https://localhost:9001/services/EchoService?wsdl

4.) Send a Test Request (for example with SoapUI) to your service at https://localhost:9001/services/EchoService
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://www.talend.org/service/">
    <soapenv:Header>
        <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="uuid_faf0159a-6b13-4139-a6da-cb7b4100c10c">
                <wsse:Username>karaf</wsse:Username>
                <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">karaf</wsse:Password>
            </wsse:UsernameToken>
        </wsse:Security>
    </soapenv:Header>
    <soapenv:Body>
        <ser:AttendeeLookupOperationRequest>
            <in>Hello</in>
        </ser:AttendeeLookupOperationRequest>
    </soapenv:Body>
</soapenv:Envelope>
You should get the following response:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <tns:EchoServiceOperationResponse xmlns:tns="http://www.talend.org/service/">
            <out>Hello World!</out>
        </tns:EchoServiceOperationResponse>
    </soap:Body>
</soap:Envelope>

Basic Authentication

1.) Disable Username/Password Authentication from previous step above.
2.) Modify wsdl file by adding a HttpBasicAuthentication policy assertion
http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/ws-securitypolicy-1.2-spec-os.html#_HttpsToken_Assertion
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="EchoService"
  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:tns="http://www.talend.org/service/"
        xmlns:wsp="http://www.w3.org/ns/ws-policy"
  targetNamespace="http://www.talend.org/service/">

   <wsdl:types>
      <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   targetNamespace="http://www.talend.org/service/">
         <xsd:element name="EchoServiceOperationRequest">
            <xsd:complexType>
               <xsd:sequence>
                  <xsd:element name="in" type="xsd:string"/>
               </xsd:sequence>
            </xsd:complexType>
         </xsd:element>
         <xsd:element name="EchoServiceOperationResponse">
            <xsd:complexType>
               <xsd:sequence>
                  <xsd:element name="out" type="xsd:string"/>
               </xsd:sequence>
            </xsd:complexType>
         </xsd:element>
      </xsd:schema>
   </wsdl:types>

   <wsdl:message name="EchoServiceOperationRequest">
      <wsdl:part name="parameters" element="tns:EchoServiceOperationRequest"/>
   </wsdl:message>
   <wsdl:message name="EchoServiceOperationResponse">
      <wsdl:part name="parameters" element="tns:EchoServiceOperationResponse"/>
   </wsdl:message>

   <wsdl:portType name="EchoServicePortType">
      <wsdl:operation name="EchoServiceOperation">
         <wsdl:input message="tns:EchoServiceOperationRequest"/>
         <wsdl:output message="tns:EchoServiceOperationResponse"/>
      </wsdl:operation>
   </wsdl:portType>

   <wsdl:binding name="EchoServiceBinding" type="tns:EchoServicePortType">
      <wsp:PolicyReference URI="#BasicAuthPolicy"/>
      <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
      <wsdl:operation name="EchoServiceOperation">
         <soap:operation soapAction="http://www.talend.org/service/EchoServiceOperation" />
         <wsdl:input>
            <soap:body use="literal" />
         </wsdl:input>
         <wsdl:output>
            <soap:body use="literal" />
         </wsdl:output>
      </wsdl:operation>
   </wsdl:binding>

   <wsdl:service name="EchoService">
      <wsdl:port name="EchoServicePort" binding="tns:EchoServiceBinding">
         <soap:address location="http://localhost:8090/services/EchoService" />
      </wsdl:port>
   </wsdl:service>

   <wsp:Policy xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="BasicAuthPolicy">
      <wsp:ExactlyOne>
         <wsp:All>
            <sp:TransportBinding xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
               <wsp:Policy>
                  <sp:TransportToken>
                     <wsp:Policy>
                        <sp:HttpsToken>
                           <wsp:Policy>
                              <sp:HttpBasicAuthentication/>
                           </wsp:Policy>
                        </sp:HttpsToken>
                     </wsp:Policy>
                  </sp:TransportToken>
                  <sp:Layout>
                     <wsp:Policy>
                        <sp:Lax/>
                     </wsp:Policy>
                  </sp:Layout>
                  <sp:AlgorithmSuite>
                     <wsp:Policy>
                        <sp:Basic128/>
                     </wsp:Policy>
                  </sp:AlgorithmSuite>
               </wsp:Policy>
            </sp:TransportBinding>
         </wsp:All>
      </wsp:ExactlyOne>
   </wsp:Policy>
</wsdl:definitions>
3.) (Re)Deploy Webservice to runtime

4.) Send a Test Request (for example with Postman) to your service with karaf:karaf credentials at https://localhost:9001/services/EchoService
After some further testing I discovered that actually no JAAS realm is involved in the Basic Authentication process. So your credentials will not be validated. The WS-Security Assertion only ensures that a Basic Authentication header is present in the request. But any username/password will be accepted. I'll do some further research to understand why this is happening and hopefully find a solution to ensure credential validation. Until then, I cannot recommend using Basic Authentication for Studio generated Jobs.

 Runtime JAAS Configuration

The reason why karaf:karaf are valid credentials is, that the runtime uses a default JAAS realm which points to a configuration file containing several users.
C:\Talend\6.3.1\runtime\etc\users.properties
tadmin=tadmin,_g_:admingroup,sl_admin
tesb=tesb,_g_:admingroup,sl_maintain
karaf = karaf,_g_:admingroup
_g_\:admingroup = group,admin,manager,viewer,systembundles
Inside the container Jetty is responsible for the HTTP transport Basic Authentication. And inside the jetty configuration karaf is defined as the default JAAS realm: C:\Talend\6.3.1\runtime\etc\jetty.xml
<Configure id="Server" class="org.eclipse.jetty.server.Server">
    . . .
    <Call name="addBean">
        <Arg>
            <New class="org.eclipse.jetty.jaas.JAASLoginService">
                <Set name="name">default</Set>
                <Set name="loginModuleName">karaf</Set>
                <Set name="roleClassNames">
                    <Array type="java.lang.String">
                        <Item>org.apache.karaf.jaas.boot.principal.RolePrincipal</Item>
                    </Array>
                </Set>
            </New>
        </Arg>
    </Call>
</Configure>

No comments:

Post a Comment