javasoapcxfws-securitywss4j

Migrating to CXF 3.2.7 -> How to solve the password related security error during SOAP RQ processing?


Context : I am trying to migrate a webservice from CXF 2.2.2 to CXF 3.2.7

Problem : Post migration whenever i try to fire the below HTTP-POST SOAP based request against my webservice through a software like SOAP UI :

<SOAP-ENV:Header>
      <wsse:Security SOAP-ENV:mustUnderstand="1">
        <wsse:UsernameToken wsu:Id="">
        <wsse:Username>sampleUser</wsse:Username>
        <wsse:Password>12345</wsse:Password>
        <wsse:PartnerID>samplePartner</wsse:PartnerID>
</wsse:UsernameToken>
</wsse:Security>
    <wsa:To>http://localhost:8080/sampleWs</wsa:To>
    <wsa:Action>http://localhost:8080/sampleWs/sampleAction</wsa:Action>
      <wsa:From>
      <wsa:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>
</wsa:From>
</SOAP-ENV:Header>

I receive the following security exception from CXF security module :

18:11:29,250 WARNING [org.apache.cxf.phase.PhaseInterceptorChain] (http-127.0.0.1:8080-1) Interceptor for {http://ws.sampleWs.varun/}SampleWebService has thrown exception, unwinding now: org.apache.cxf.binding.soap.SoapFault: A security error was encountered when verifying the message
        at org.apache.cxf.ws.security.wss4j.WSS4JUtils.createSoapFault(WSS4JUtils.java:234) [cxf-rt-ws-security-3.2.7.jar:3.2.7]
        at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessageInternal(WSS4JInInterceptor.java:341) [cxf-rt-ws-security-3.2.7.jar:3.2.7]
        at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:176) [cxf-rt-ws-security-3.2.7.jar:3.2.7]
        at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:87) [cxf-rt-ws-security-3.2.7.jar:3.2.7]
        at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308) [cxf-core-3.2.7.jar:3.2.7]
        at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) [cxf-core-3.2.7.jar:3.2.7]
        .
        .
        .
Caused by: org.apache.wss4j.common.ext.WSSecurityException: BSP:R4201: Any PASSWORD MUST specify a Type attribute
        at org.apache.wss4j.common.bsp.BSPEnforcer.handleBSPRule(BSPEnforcer.java:57) [wss4j-ws-security-common-2.2.2.jar:2.2.2]
        at org.apache.wss4j.dom.message.token.UsernameToken.checkBSPCompliance(UsernameToken.java:834) [wss4j-ws-security-dom-2.2.2.jar:2.2.2]
        at org.apache.wss4j.dom.message.token.UsernameToken.<init>(UsernameToken.java:143) [wss4j-ws-security-dom-2.2.2.jar:2.2.2]
        at org.apache.wss4j.dom.processor.UsernameTokenProcessor.handleUsernameToken(UsernameTokenProcessor.java:137) [wss4j-ws-security-dom-2.2.2.jar:2.2.2]
        at org.apache.wss4j.dom.processor.UsernameTokenProcessor.handleToken(UsernameTokenProcessor.java:62) [wss4j-ws-security-dom-2.2.2.jar:2.2.2]
        at org.apache.wss4j.dom.engine.WSSecurityEngine.processSecurityHeader(WSSecurityEngine.java:340) [wss4j-ws-security-dom-2.2.2.jar:2.2.2]
        at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessageInternal(WSS4JInInterceptor.java:285) [cxf-rt-ws-security-3.2.7.jar:3.2.7]
        ... 28 more

The root cause appears to be a missing attribute in wsse:password tag.

I checked the security WS specs : http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd

There i could not find a mandatory type attribute for wsse:passwordas expected by latest CXF.

Note : The same request is processed fine by CXF version 2.2.2

Question : Is there a way for preventing CXF from dropping the above request and allow it go through. I looked around a lot but couldnt find any answers ? Any suggestions ? OR modfifying the SOAP request is the only solution ?


Solution

  • Above request is being dropped because as stated earlier by @GPI, CXF tries to enforce R4201 of the Basic security specs (http://www.ws-i.org/profiles/basicsecurityprofile-1.1.html).

    To prevent CXF from enforcing this we can use configuration constants provided by ws-security and wss4j that would instruct CXF to stop the enforcement.

    Solution #1 (Using WSS4J interceptor)

    In your spring config file, you can set isBspCompliant to false :

        <jaxws:inInterceptors>
            <bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
                <constructor-arg>
                    <map>
                        <entry key="action" value="UsernameToken" />
                        <entry key="passwordType" value="PasswordText" />
                        <entry key="passwordCallbackRef">
                            <ref bean="passwordCallback" />
                        </entry>
                        <entry key="isBSPCompliant" value="false"/>
                    </map>
                </constructor-arg>
            </bean>
        </jaxws:inInterceptors>
    

    Solution #2 (Using JAX-WS)

    In your spring config file, you can set ws-security.is-bsp-compliant to false :

        <jaxws:endpoint id="sample" implementor="sample.ws.SampleWebService" address="/SampleWebService">
        <jaxws:properties> 
        <entry key="ws-security.is-bsp-compliant" value="false"/> 
        </jaxws:properties> 
    </jaxws:endpoint>
    

    For additional configuration options, you can refer these pages :

    http://ws.apache.org/wss4j/config.html

    http://cxf.apache.org/docs/ws-securitypolicy.html