I am trying to connect to a web service using WS-Security UsernameToken spec 1.0, using apache cxf 2.4.0.
I've copied the code below from the CXF docs, but am getting: org.apache.cxf.ws.policy.PolicyException: No username available
    MyService_Service ss = new MyService_Service(wsdlURL, SERVICE_NAME);
    MyService port = ss.getBasicHttpBindingMyService ();  
    Client client = ClientProxy.getClient(port);
    Endpoint cxfEndpoint = client.getEndpoint();
    Map<String,Object> outProps = new HashMap<String,Object>();
    outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
    outProps.put(WSHandlerConstants.USER, "USERNAME");
    outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
    outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, 
    ClientPasswordHandler.class.getName());
    WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
    cxfEndpoint.getOutInterceptors().add(wssOut);
I've also implemented a ClientPasswordHandler class, again from the docs, but it seems like the username is never sent (according to the error). Here is the password handler:
public class ClientPasswordHandler implements CallbackHandler {
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
    WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
    pc.setPassword("Password");     
    }
}
Is there any way to see if the WSS4Jinterceptor is being applied, and the UsernameToken is sent?
CXF relies on WSS4J in large part to implement WS-Security. Within your own services, WS-Security can be activated by using WS-SecurityPolicy, which provides a comprehensive and sophisticated validation of the security properties of a received message.
In Apache Camel, the Camel CXF component is the key to integrating routes with Web services. You can use the Camel CXF component to create a CXF endpoint, which can be used in either of the following ways: Consumer — (at the start of a route) represents a Web service instance, which integrates with the route.
Class WSS4JOutInterceptorProperty name for a map of action IDs ( Integer ) to action class names.
Are you getting the PolicyException on the client side? If so, that likely means the WSDL you are using has a WS-SecucurityPolicy fragment in it that describes the UsernameToken policy that it wants and is expecting. If that's the case, then you shouldn't configure the WSS4JOutInterceptor at all. The WS-Policy runtime will handle it and you just need to provide some properties that it may need.
The docs for the SecurityPolicy stuff are at: http://cxf.apache.org/docs/ws-securitypolicy.html
You likely just need to use:
Map ctx = ((BindingProvider)port).getRequestContext();
ctx.put("ws-security.username", "USERNAME");
ctx.put("ws-security.password", "Password");
Thanks to Daniel the full working configuration for me is the following:
    webServicePort = webService_service.getPort(WebService.class);
    Client client = ClientProxy.getClient(webServicePort);
    Endpoint cxfEndpoint = client.getEndpoint();
    Map<String, Object> props = ((BindingProvider) webServicePort).getRequestContext();
    props.put("ws-security.username", PravoRuConstants.USERNAME);
    props.put("ws-security.password", PravoRuConstants.PASSWORD);
    props.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
    props.put(WSHandlerConstants.USER, PravoRuConstants.USERNAME);
    props.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
    props.put(WSHandlerConstants.PW_CALLBACK_CLASS, PravoRuPasswordHandler.class.getName());
    WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(props);
    cxfEndpoint.getOutInterceptors().add(wssOut);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With