Many Thanks David for your efforts in helping me out. That will be very helpful.
 
Will it be a good idea to forward my doubt to CXF and WSS4J developers community?
 
Best Regards,
Rahul

 
On Mon, Jul 27, 2009 at 1:35 AM, David Jencks <david_jencks@yahoo.com> wrote:
I chatted with Rahul on IRC a bit, and it looks to me as if his code is doing what cxf and wss4j expect.

I think the next step is to figure out exactly where the fault is coming from.

I would grep the cxf and wss4j source code for "but a password is needed".  If that doesn't find the source I would run geronimo in the debugger and put a breakpoint at the end of the handle(CallbackHandler handler) method and step through the code.

I also wonder if the fault is from the WSS4jOutInterceptor.

thanks
david jencks

On Jul 26, 2009, at 4:20 PM, rahul.soa wrote:

Just one amendment here in my speculation about the fault cause.

I wrote this in the previous thread,


"but I dont know why I am getting this error pwd == null but a password is needed at pwcb.setPassword(passwd);"

Now, i dont think this fault is coming from here
pwcb.setPassword(passwd);

as I have tested it by removing the following code to be sure about the fault

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

from ServerPasswordHandler and I still have the same fault error in the response.

Please correct me if I am wrong somewhere. I am not sure where this fault come from?

Thank you.

Best Regards,
Rahul
On Mon, Jul 27, 2009 at 12:07 AM, rahul.soa <rahul.soa@googlemail.com> wrote:
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