Hello David/Devs, Objective: trying to set web service security at serverside:
I am getting an error while accessing the secured webservice. The soap fault I am receiving is below: *Response:* <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/ "><soap:Body><soap:Fault><faultcode>soap:Server</faultcode><faultstring>*pwd == null but a password is needed* </faultstring></soap:Fault></soap:Body></soap:Envelope> * Request:* <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><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: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" wsu:Id="UsernameToken-32620541"><wsse:Username xmlns:wsse=" http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">system</wsse:Username><wsse:Password xmlns:wsse=" http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" Type=" http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">manager</wsse:Password></wsse:UsernameToken></wsse:Security></soap:Header><soap:Body><add xmlns="http://jws.samples.geronimo.apache.org "><value1>2</value1><value2>2</value2></add></soap:Body></soap:Envelope> How I am trying to do is, 1. At, server side (in the doPublish method of CXFEndpoint), I am setting the WSS4JIn/OutInterceptor property for user token (please note: this is not generic code at this moment) protected void doPublish(String baseAddress) { // XXX: assume port 8080 by default since we don't know the actual port // at startup String address = (baseAddress == null) ? "http://localhost:8080" : baseAddress; JaxWsServerFactoryBean svrFactory = new GeronimoJaxWsServerFactoryBean(); svrFactory.setBus(bus); svrFactory.setAddress(address + this.portInfo.getLocation()); svrFactory.setServiceFactory(serviceFactory); svrFactory.setStart(false); svrFactory.setServiceBean(implementor); if (HTTPBinding.HTTP_BINDING.equals(implInfo.getBindingType())) { svrFactory.setTransportId(" http://cxf.apache.org/bindings/xformat"); } // to receive the incoming username/password in soap request Map inProps = new HashMap(); inProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN); inProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT); inProps.put(WSHandlerConstants.USER, "system"); inProps.put(WSHandlerConstants.PW_CALLBACK_REF, new *ServerPasswordHandler*()); server = svrFactory.create(); // to receive the secure header WSS4JInInterceptor wssIn = new WSS4JInInterceptor(inProps); // to send the secure soap header WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(inProps); init(); org.apache.cxf.endpoint.Endpoint endpoint = getEndpoint(); endpoint.getInInterceptors().add(wssIn); endpoint.getInInterceptors().add( new org.apache.cxf.binding.soap.saaj.SAAJInInterceptor()); endpoint.getOutInterceptors().add(wssOut); endpoint.getOutInterceptors().add( new org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor()); LOG.debug("So far set the interceptor"); // if (getBinding() instanceof SOAPBinding && this.portInfo.isMTOMEnabled() != null) { ((SOAPBinding) getBinding()).setMTOMEnabled(this.portInfo .isMTOMEnabled()); } server.start(); LOG.debug("Invoked"); } I am setting up the login authentication and setting the password in the Server Handler, like following: public class ServerPasswordHandler implements CallbackHandler { private static final Logger LOG = LoggerFactory .getLogger(ServerPasswordHandler.class); public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) { WSPasswordCallback pwcb = (WSPasswordCallback) callbacks[i]; if (pwcb.getUsage() == WSPasswordCallback.USERNAME_TOKEN_UNKNOWN) { LOG.debug("I am inside the ServerPasswordHandler"); String username = pwcb.getIdentifier(); String passwd = pwcb.getPassword(); LoginContext context = null; try { // Login authentication goes here // use the existing security realm for the moment for testing context = ContextManager.login("geronimo-admin", new UsernamePasswordCallbackHandler(username, passwd)); // ContextManager.login(realm, callbackHandler, // configuration) context.login(); LOG.debug("login is successful"); } catch (LoginException e) { LOG.debug("login failed"); throw new IOException("Unable to verify " + username + " and " + passwd); } //TODO: what to do with subject Subject subject = context.getSubject(); ContextManager.setCallers(subject, subject); if (!pwcb.getPassword().equals(passwd)) { LOG.debug("wrong password"); throw new IOException("wrong password"); } else { *LOG.debug("I am setting the password here ::::" + passwd);* * pwcb.setPassword(passwd);* } } } } } In the traces, I can see the password value is "manager" which is sent by client I am setting the password here ::::manager but I dont know why I am getting this error pwd == null but a password is needed at pwcb.setPassword(passwd); Login authentication goes sucessful when the client provides the correct username and password (which are "system and "manager" respectively). and goes unsuccessful otherwise. The full trace from the geronimo.log is attached here: (there are some debug statement to see the traces ) 2009-07-27 01:26:17,809 DEBUG [JAXWSServiceReference] Initializing service with: file:/home/rahul/new_workspace1/GerominoWebClient/WEB-INF/wsdl/CalculatorService.wsdl {http://jws.samples.geronimo.apache.org}Calculator 2009-07-27 01:26:18,031 DEBUG [PortMethodInterceptor] Set address property: http://localhost:8080/GerominoWeb/calculator 2009-07-27 01:26:18,031 DEBUG [CXFPortMethodInterceptor] Username and password sent by Clients are : system manager 2009-07-27 01:26:18,126 DEBUG [CXFPasswordHandler] I HAVE SET THE VALUES system and manager 2009-07-27 01:26:18,142 DEBUG [ServerPasswordHandler] I am inside the ServerPasswordHandler 2009-07-27 01:26:18,143 DEBUG [UsernamePasswordCallbackHandler] WHAT I GOT HERE: system and manager 2009-07-27 01:26:18,143 DEBUG [UsernamePasswordCallbackHandler] Username set to: system 2009-07-27 01:26:18,143 DEBUG [UsernamePasswordCallbackHandler] password set to: manager 2009-07-27 01:26:18,144 DEBUG [UsernamePasswordCallbackHandler] WHAT I GOT HERE: system and manager 2009-07-27 01:26:18,144 DEBUG [UsernamePasswordCallbackHandler] Username set to: system 2009-07-27 01:26:18,144 DEBUG [UsernamePasswordCallbackHandler] password set to: manager *2009-07-27 01:26:18,144 DEBUG [ServerPasswordHandler] login is successful* *2009-07-27 01:26:18,145 DEBUG [ServerPasswordHandler] I am setting the password here ::::manager* *2009-07-27 01:26:18,313 INFO [PhaseInterceptorChain] Interceptor has thrown exception, unwinding now pwd == null but a password is needed* 2009-07-27 01:26:18,376 ERROR [log] /jaxws-calculator/calculator *javax.xml.ws.soap.SOAPFaultException: pwd == null but a password is needed* at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:145) at $Proxy67.add(Unknown Source) at CalculatorServlet.doGet(CalculatorServlet.java:42) at javax.servlet.http.HttpServlet.service(HttpServlet.java:693) at javax.servlet.http.HttpServlet.service(HttpServlet.java:806) at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:521) at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:435) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:118) at org.eclipse.jetty.server.session.SessionHandler.handle(SessionHandler.java:179) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:928) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:370) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:862) at org.apache.geronimo.jetty7.handler.GeronimoWebAppContext.doScope(GeronimoWebAppContext.java:107) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:116) at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:243) at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:126) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:115) at org.eclipse.jetty.server.Server.handle(Server.java:337) at org.eclipse.jetty.server.HttpConnection.handleRequest(HttpConnection.java:561) at org.eclipse.jetty.server.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:943) at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:530) at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:203) at org.eclipse.jetty.server.HttpConnection.handle(HttpConnection.java:414) at org.eclipse.jetty.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:437) at org.apache.geronimo.pool.ThreadPool$1.run(ThreadPool.java:214) at org.apache.geronimo.pool.ThreadPool$ContextClassLoaderRunnable.run(ThreadPool.java:344) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:619) *Caused by: org.apache.cxf.binding.soap.SoapFault: pwd == null but a password is needed* at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.unmarshalFault(Soap11FaultInInterceptor.java:75) at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInInterceptor.java:46) at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInInterceptor.java:35) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:226) at org.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage(AbstractFaultChainInitiatorObserver.java:96) at org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:69) at org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:34) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:226) at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:641) at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:2102) at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1980) at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1905) at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:66) at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:600) at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:226) at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:469) at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:299) at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:251) at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:73) at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:124) ... 28 more Can you please let me know or correct me, why this is happening?, I think if password is set correctly in the pwcb.setPassword(passwd); then client should be able to access the secure web service. I am getting the correct password "manager" (as seen in the logs) and setting the same but I dont know why I am getting this fault. Second thing is, I am not sure what to do with subject? Am I missing something in the above code? Please correct me and help me in this. Many Thanks in advance for your response. Regards, Rahul