« Return to Thread: WS-Security and CXF

WS-Security and CXF

by dmadunic :: Rate this Message:

Reply to Author | View in Thread

Hi all,
i have two questions concerning how to implement WS-Security with CXF.

1) First question: how on the server side to read CallbackHandler supplied password?

Followoing instructions on CXF homesite and from several articles, I have created simple HelloWorldService and attached to it following interceptors:

        <jaxws:endpoint  id="helloWorld" implementor="demo.spring.HelloWorldImpl" address="/HelloWorld" >
                <jaxws:inInterceptors>
                        <bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor"/>
                        <bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
                                <property name="properties">
                                        <map>
                                                <entry key="action" value="UsernameToken"/>
                                                <entry key="passwordType" value="PasswordText"/>
                                                <entry key="passwordCallbackClass" value="demo.interceptors.AuthenticationCallbackHandler"/>
                                        </map>
                                </property>
                        </bean>
                        <bean class="demo.interceptors.ValidateUserTokenInterceptor"/>
                </jaxws:inInterceptors>

        </jaxws:endpoint>

AuthenticationCallbackHandler is very simple it just does the following:

public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
                WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
               
                if (pc.getIdentifer().equals("joe")) {
                        pc.setPassword("password");
                }
        }

I also wrote my demo.interceptors.ValidateUserTokenInterceptor which should Validate received token.

public void handleMessage(Message message) throws Fault {
                boolean userTokenValidated = false;

                logger.debug("Invoked - ValidateUserToken: " + message);

                //logger.debug("messagePwd: " + message.get);
                Vector result = (Vector) message.getContextualProperty(WSHandlerConstants.RECV_RESULTS);

                if (result==null) {
                        throw new IllegalArgumentException(WSHandlerConstants.RECV_RESULTS + " Property not found in MessageContext?!");
                }

                for (int i = 0; i < result.size(); i++) {
                        WSHandlerResult res = (WSHandlerResult) result.get(i);
                        for (int j = 0; j < res.getResults().size(); j++) {
                                WSSecurityEngineResult secRes = (WSSecurityEngineResult) res.getResults().get(j);
                                int action = secRes.getAction();
                                logger.debug("Checking: " + secRes);
                                // USER TOKEN
                                if ((action & WSConstants.UT) > 0) {
                                        WSUsernameTokenPrincipal principal = (WSUsernameTokenPrincipal) secRes.getPrincipal();
                                        logger.debug("name=" + principal.getName());
                                        logger.debug("password=" + principal.getPassword());
                                        logger.debug("passwordType=" + principal.getPasswordType());
                                        logger.debug("createdTime=" + principal.getCreatedTime());

                                        if (principal.getPassword() == null) {
                                                throw new RuntimeException("Invalid Security Header");
                                        } else {
                                                // NOW COMPARE PASSWORDS - HOW????
                                                userTokenValidated = true;
                                        }
                                }
                        }
                }
                if (!userTokenValidated) {
                        throw new RuntimeException("Security processing failed");
                }
        }

So far i was able to read information from WSSE:Security header - ie. username and pwd supplied by the Client. But i do not know how to address the password value supplied by AuthenticationCallbackHandler inside this interceptor??

2) Second question: how to properly configure interceptors on client using spring?

To test the service i wrote simple HelloClient:

public static void main(String[] args) {

                ApplicationContext context = new ClassPathXmlApplicationContext("/clientAppContext.xml");
                HelloWorld client = (HelloWorld) context.getBean("client");
                System.out.println("Invoking service...");
                String text = client.sayHi("Domagoj");
                System.out.println("Response=: " + text);
        }

This is my clientAppContext.xml:

<bean id="client" class="demo.spring.HelloWorld"  factory-bean="clientFactory" factory-method="create"/>

        <bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
          <property name="serviceClass" value="demo.spring.HelloWorld"/>
          <property name="address" value="http://localhost:8080/SoaLab/HelloWorld"/>
          <property name="outInterceptors">
                        <list>
                                <bean class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor"/>
                                <bean class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
                                        <property name="properties">
                                                <map>
                                                        <entry key="action" value="UsernameToken"/>
                                                        <entry key="user" value="joe"/>
                                                        <entry key="passwordType" value="PasswordText"/>
                                                        <entry key="passwordCallbackClass" value="demo.interceptors.ClientPasswordCallback"/>
                                                </map>
                                        </property>
                                </bean>
                        </list>
                </property>
        </bean>

The problem i have is that Response i receive from HelloWorld service is null??
If i comment interceptors on both client and server side it all works fine.

Any suggestions?

Thx in advance....

 « Return to Thread: WS-Security and CXF