webservice client using cxf (JaxWsProxyFactoryBean) to test digest authentication

user2784616 picture user2784616 · Sep 22, 2013 · Viewed 7.9k times · Source

How do I setup digest auth type to webservice client using cxf (JaxWsProxyFactoryBean) ? As of now my client by default assumes Basic auth type when I set the username password in the factory object. And the request message header have "Authentication [Basic: ......]" in it. I want to setup a cxf client for digest auth. could you please assist ? (WS is implemented in Java using CXF and Spring 3)

I have configured spring security for Digest auth as follows...

<security:http entry-point-ref="digestEntryPoint">
      <security:intercept-url pattern="/**" requires-channel="any" access="ROLE_WS_USER" />
     <security:custom-filter ref="digestAuthenticationFilter" position="BASIC_AUTH_FILTER"/>
 </security:http>



<bean id="digestAuthenticationFilter" class="org.springframework.security.web.authentication.www.DigestAuthenticationFilter">
      <property name="userDetailsService" ref="userService"/>
     <property name="authenticationEntryPoint" ref="digestEntryPoint"/>
 </bean>


<bean id="digestEntryPoint" class="org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint">
     <property name="realmName" value="My Webservice"/>
    <property name="key" value="acegi"/>
     <property name="nonceValiditySeconds" value="10" />
</bean>



<bean id="userService" class="com.wallstreetsystems.ws.config.SpringSecurityUserDetailsService">
 </bean>

<security:authentication-manager>
     <security:authentication-provider user-service-ref="userService"/>
</security:authentication-manager>

And the java client is...

public static void main(String args[]) throws Exception {
 JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
  factory.setServiceClass(OrderNUmber.class);
 factory.setAddress(ht..://localh..:9000/ws/OderNumberService);
  factory.setUsername("bob");

 Map<String, Object> outProps = new HashMap<String, Object>();
  outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
  outProps.put(WSHandlerConstants.USER,"bob");
 outProps.put(WSHandlerConstants.PASSWORD_TYPE,WSConstants.PW_DIGEST);
  outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientPasswordCallback.class.getName());
  WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
 factory.getOutInterceptors().add(wssOut);


 String orderNo = orderNumber.getNextOrderNumber();
        System.out.println(orderNo);
 }

I am deploying and running test on embedded Jetty. Error log is as follows....

ID: 1
Address: ht..://localh...:9000/ws/OrderNumberService
 Encoding: UTF-8
Content-Type: text/xml
Headers: {Accept=[*/*], SOAPAction=["getNextOrderNumber"]}
Payload: <soap:Envelope xmlns:soap="ht..://schemas.xmlsoap.org/soap/envelope/"><soap:Header><wsse:Security xmlns:wsse="ht..://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="ht..://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" soap:mustUnderstand="1"><wsse:UsernameToken wsu:Id="UsernameToken-1"><wsse:Username>bob</wsse:Username><wsse:Password Type="ht..://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">bobspassword</wsse:Password></wsse:UsernameToken></wsse:Security></soap:Header><soap:Body/></soap:Envelope>
 --------------------------------------
2013-09-23 14:07:36,887 [294071597@qtp-1153274506-2] INFO  org.apache.cxf.services.OrderNumberService.OrderNumberPort.OrderNumber - Inbound Message
----------------------------
 ID: 2
Address: ht..://localhost:9000/ws/OrderNumberService
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml; charset=UTF-8
Headers: {Accept=[*/*], Cache-Control=[no-cache], connection=[keep-alive], Content-Length=[616], content-type=[text/xml; charset=UTF-8], Host=[localhost:9000], Pragma=[no-cache], SOAPAction=["getNextOrderNumber"], User-Agent=[Apache CXF 2.6.2]}
 Payload: <soap:Envelope xmlns:soap="ht..://schemas.xmlsoap.org/soap/envelope/"><soap:Header><wsse:Security xmlns:wsse="ht..://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="ht..://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" soap:mustUnderstand="1"><wsse:UsernameToken wsu:Id="UsernameToken-1"><wsse:Username>bob</wsse:Username><wsse:Password Type="ht..://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">bobspassword</wsse:Password></wsse:UsernameToken></wsse:Security></soap:Header><soap:Body/></soap:Envelope>
 --------------------------------------
2013-09-23 14:07:36,911 [294071597@qtp-1153274506-2] WARN  org.apache.cxf.phase.PhaseInterceptorChain - Interceptor for {ht..://www.xyz.com}OrderNumberService#{ht..://www.xyz.com}getNextOrderNumber has thrown exception, unwinding now
 org.apache.cxf.binding.soap.SoapFault: MustUnderstand headers: [{ht..://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security] are not understood.
  at org.apache.cxf.binding.soap.interceptor.MustUnderstandInterceptor.checkUltimateReceiverHeaders(MustUnderstandInterceptor.java:150)
 at org.apache.cxf.binding.soap.interceptor.MustUnderstandInterceptor.handleMessage(MustUnderstandInterceptor.java:96)
  at org.apache.cxf.binding.soap.interceptor.MustUnderstandInterceptor.handleMessage(MustUnderstandInterceptor.java:49)
 at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262)
 at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
  at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:211)
 at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:213)
 at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:193)
  at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:130)
 at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:221)
 at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:141)
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
 at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:197)
 at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:502)
  at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1148)
 at com.myproject.ws.config.WSSWebSecurityFilterChain.doFilter(WSSWebSecurityFilterChain.java:64)
 at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1139)
  at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:378)
 at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
 at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
  at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
 at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:417)
 at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
  at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
 at org.mortbay.jetty.Server.handle(Server.java:324)
 at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:535)
 at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:880)
  at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:747)
 at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
 at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
 at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
  at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:520)
2013-09-23 14:07:36,940 [main] INFO  org.apache.cxf.services.OrderNumberService.OrderNumberPort.OrderNumber - Inbound Message
----------------------------
 ID: 1
Response-Code: 500
Encoding: UTF-8
Content-Type: text/xml; charset=utf-8
Headers: {Content-Length=[340], content-type=[text/xml; charset=utf-8], Server=[Jetty(6.1.15)]}
Payload: <soap:Envelope xmlns:soap="ht..://schemas.xmlsoap.org/soap/envelope/"><soap:Body><soap:Fault><faultcode>soap:MustUnderstand</faultcode><faultstring>MustUnderstand headers: [{ht..://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security] are not understood.</faultstring></soap:Fault></soap:Body></soap:Envelope>
 --------------------------------------
2013-09-23 14:07:37,021 [main] INFO  /ws - Closing Spring root WebApplicationContext

Problem : As you can see in the request message header there is no "Authentication [Digest:...." and the request is treated as normal one without auth. But when request reaches service provider which is configured to intercept the Digest request throws the error.

I wanted to set the Authentication type to Digest in the client, so that request would be treated as Digest request.

Answer

user2784616 picture user2784616 · Sep 24, 2013

This is how I fixed it:

JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); 
factory.setAddress("localhost:9000/OrderNumberService"); 
OrderNumberService orderNumberClient = factory.create(OrderNumberService.class); 
Client client = ClientProxy.getClient(orderNumberClient); 
HTTPConduit http = (HTTPConduit) client.getConduit(); 
AuthorizationPolicy authPolicy = new AuthorizationPolicy(); 
authPolicy.setAuthorizationType("Digest"); 
authPolicy.setUserName("foo"); 
authPolicy.setPassword("bar"); 
http.setAuthorization(authPolicy);