Search code examples
javasoapcxfws-securitywss4j

What is the correct configuration for a CXF SOAP Service with UsernameTokenSignature?


I'm trying to setup a CXF Service and Client using UsernameTokenSignature. Startingpoint is an existing, code first, service. Unfortunatly all examples I found use WS-Policy, which is - as I understand - not supported by CXF in a code first scenario.

I managed to create a client which sends messages like I expect using this configuration:

Client:

<jaxws:client id="clientWithUsernameTokenSignature" serviceClass="mypackage.MyServiceInterface" address="http://localhost:8081/ws-security-secured-soap-service/services/Service_v1">
    <jaxws:outInterceptors>
        <ref bean="WSS4JOutInterceptor_UsernameTokenSignature" />
    </jaxws:outInterceptors>
</jaxws:client>

WSS4JOutInterceptor

 <bean class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor" id="WSS4JOutInterceptor_UsernameTokenSignature">
    <constructor-arg>
        <map>
            <entry key="action" value="UsernameTokenSignature" />
            <entry key="user" value="Admin" />
            <entry key="passwordCallbackClass" value="mypackage.ClientCallbackHandler" />
        </map>
    </constructor-arg>
</bean>

However I failed setting up a service to process the messages from this client correctly. I tried:

Service:

<jaxws:endpoint id="soapServ_v3" implementor="#myServiceFacade" address="/MyService_v1">
        <jaxws:inInterceptors>
            <ref bean="WSS4JInInterceptor_UsernameTokenSignature" />
        </jaxws:inInterceptors>
</jaxws:endpoint>

WSS4JInInterceptor

<bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor" id="WSS4JInInterceptor_UsernameTokenSignature">
    <constructor-arg>
        <map>
            <entry key="action" value="UsernameTokenSignature" />
            <entry key="passwordCallbackClass" value="mypackage.ServerCallbackHandler" />
        </map>
    </constructor-arg>
</bean>

Doing this the server doesn't accept messages from the client and responds with a security error. Debugging I found that the first place it fails is in verifyUnknownPassword of org.apache.wss4j.dom.validate.UsernameTokenValidator. Here allowUsernameTokenDerivedKeys is set to false. I presume there is some configuration I can set to get this to to true.

Which is the correct configuration on the server to allow username token derived keys?

Even if I use the debugger to change the value to true the service call still fails. In that case the interceptor throws an exception at checkActions: 'An error was discovered processing the header'.

So I presume there's something else I need to configure aswell. Anyone knows how to set this up correctly?


Solution

  • Ok I finally figured it out. The boolean property 'allowUsernameTokenNoPassword' needs to be set to 'true' so that the server accepts a UT with no password. Then to pass the security header check additionally 'UsernameTokenNoPassword' needs to be added as action.

    The working configuration looks like this:

    WSS4JInInterceptor:

    <bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor" id="WSS4JInInterceptor_UsernameTokenSignature">
        <constructor-arg>
            <map>
                <entry key="action" value="UsernameTokenSignature UsernameTokenNoPassword" />
                <entry key="allowUsernameTokenNoPassword" value="true" />
                <entry key="passwordCallbackClass" value="mypackage.ServerCallbackHandler" />
            </map>
        </constructor-arg>
    </bean>