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);
}
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.
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);