WS-Security UsernameToken with Apache CXF

18,683

You are using WS-SecurityPolicy as per the code you shared. How about using WS-Security only and sending across the usernametoken using WSS4JOutInterceptor?

Check the section "Adding the interceptors via the API" in apache cfx ws-security guide here : http://cxf.apache.org/docs/ws-security.html

This is what needs to be done as per the above apache cxf documenation above. You might only need the out interceptor path.

On the client side, you can obtain a reference to the CXF endpoint using the ClientProxy helper:

import org.apache.cxf.frontend.ClientProxy;
...

GreeterService gs = new GreeterService();
Greeter greeter = gs.getGreeterPort();
...
org.apache.cxf.endpoint.Client client = ClientProxy.getClient(greeter);
org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();

Now you're ready to add the interceptors:

import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;
import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;
...

Map<String,Object> inProps = new HashMap<String,Object>();
... // how to configure the properties is outlined below;

WSS4JInInterceptor wssIn = new WSS4JInInterceptor(inProps);
cxfEndpoint.getInInterceptors().add(wssIn);

Map<String,Object> outProps = new HashMap<String,Object>();
outProps.put("action", "UsernameToken Timestamp");
outProps.put("passwordType", "PasswordDigest"); //remove this line if want to use plain text password
outProps.put("user", "abcd");
outProps.put("passwordCallbackClass", "demo.wssec.client.UTPasswordCallback");

WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
cxfEndpoint.getOutInterceptors().add(wssOut);

You will need to write password callback class (UTPasswordCallback) in the example above.

Apache cxf has a complete sample for UserName token here: http://svn.apache.org/repos/asf/cxf/trunk/distribution/src/main/release/samples/ws_security/ut/

From the above link browse to client folder (src/main/java/demo/wssec/client) for user name token and UTPasswordCallback code.

EDIT: If your wsdl expects password as plain text then just remove this line from the code: outProps.put("passwordType", "PasswordDigest");

Share:
18,683
user1007895
Author by

user1007895

Updated on June 11, 2022

Comments

  • user1007895
    user1007895 almost 2 years

    I have a java application that interacts with a SOAP service. I used the WSDL to generate a java client via CXF, but I need to authenticate my calls using ws-security. I am looking for a code-only way to do this, and I don't have any xml configurations. This is what I have tried:

    Map ctx = ((BindingProvider)port).getRequestContext();
    ctx.put("ws-security.username", "joe");
    ctx.put("ws-security.password", "joespassword");
    port.makeSoapCall();
    

    But I get a parse error for invalid WS-Security header. What is the right way to do this?

    In SOAP UI, I can do this easily by right-clicking the soap header, clicking "Add WSS UsernameToken", and selecting "Password Text"