Apache CXF - credentials not being sent from WSS4JOutInterceptor?
Asked Answered
H

4

10

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?

Harmonyharmotome answered 6/5, 2011 at 2:20 Comment(0)
E
20

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");
Ezequiel answered 6/5, 2011 at 2:35 Comment(3)
Daniel Kulp your answer didn't work for me. I see the console, and the exception is: General Web Service security ExceptionGretna
Thanks Daniel. I have been looking for this for hours.Nightie
Daniel, It might be too old. But, I need to know, if I like my password type to be text and want to add nonce, how do I do that here?Ivoryivorywhite
N
3

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);
Nomination answered 16/2, 2018 at 14:56 Comment(1)
Your configuration works for me too, with just a "little" difference. I had NOT to add the interceptor to the endpoint out interceptors (last line in your snippet) otherwise I get the username_token header printed twice in my request.Usufruct
C
1

On using the answer from Daniel, I was getting the following exception

Caused by: org.apache.cxf.transport.http.HTTPException: HTTP response '401: Unauthorized' when communicating with http://..
at .apache.cxf.inorg.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1555)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1494)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1402)
at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:649)
at orgterceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:535)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:465)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:368)

I used the below and it started working

Map ctx = ((BindingProvider) ssPort).getRequestContext();
        ctx.put(BindingProvider.USERNAME_PROPERTY, "user");
        ctx.put(BindingProvider.PASSWORD_PROPERTY, "pass");
        ctx.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://c
Chaqueta answered 21/4, 2015 at 11:22 Comment(0)
H
1

First, I only added the properties mentioned to the ctx. and it didn't work Then I removed the old instructions about:

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

And finally it WORKED!

Thanks!!!

Heartthrob answered 9/6, 2023 at 20:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.