0

Since yesterday, I'm trying to integrate security into my web services soap (with apache cxf) via ws-security. For this I have the following configuration: --my endppoint and its interceptors configuration:

@Configuration 
@ImportResource({"classpath:META-INF/cxf/cxf.xml"})
@ComponentScan(basePackages ={"com.nhit.dev"})
public class MyConfig extends SpringBootServletInitializer{



@Bean
public IServicesWeb momoService() {
    return new MomoServices();
}

@Bean(name = Bus.DEFAULT_BUS_ID)
public SpringBus springBus() {
    return new SpringBus();
} 


@Bean
public ServletRegistrationBean cxfServlet() {
    ServletRegistrationBean servlet = new ServletRegistrationBean(new   CXFServlet(), "/services/*");
    servlet.setLoadOnStartup(1);
    return servlet;
}

@Bean
public Endpoint endpoint() {

EndpointImpl endpoint = new EndpointImpl(springBus(), momoService());
endpoint.publish("/momo");
Map<String, Object> inProps = new HashMap<String, Object>();
inProps.put("action", "UsernameToken");
inProps.put("passwordType", "PasswordText");
inProps.put("passwordCallbackClass",  "com.nhit.dev.mobilepayment.web.WsPwdCallBack");
endpoint.getInInterceptors().add(new WSS4JInInterceptor(inProps));

        Map<String, Object> outProps = new HashMap<String, Object>();
    outProps.put("action", "UsernameToken");
    outProps.put("user", "abc");
    outProps.put("passwordType", "PasswordText");
    outProps.put("passwordCallbackClass", "com.nhit.dev.mobilepayment.web.WsPwdCallBack");
    endpoint.getOutInterceptors().add(new WSS4JOutInterceptor(outProps));
    return endpoint;
}

}

--my PasswordCallBack class handler:

public class WsPwdCallBack implements CallbackHandler{

protected final Log logger = LogFactory.getLog(getClass());

private Map<String, String> passwords = new HashMap<String, String>();

public WsPwdCallBack() {
    passwords.put("abc", "abc");
    passwords.put("xyz", "xyz");
}

public void handle(Callback[] callbacks) throws IOException,
        UnsupportedCallbackException {
    for (int i = 0; i < callbacks.length; i++) {
        WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];

        String pass = passwords.get(pc.getIdentifier());
        if (pass != null) {
            pc.setPassword(pass);
            return;
        }
    }
}

}

--finally my soap request from soapUI:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://webservices.web.mobilepayment.dev.nhit.com/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
   <soapenv:Header>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" soapenv:mustUnderstand="1">
         <wsse:UsernameToken wsu:Id="UsernameToken-87b7b0c5-31fe-4a01-b333-f9ca564ded57">
            <wsse:Username>xyz</wsse:Username>
            <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">TlPGdyb/NOoeA2KMO0n6DbmA0AA=</wsse:Password>
            <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">FCG+tTtuZXguO8nUQUQeIQ==</wsse:Nonce>
            <wsu:Created>2016-12-08T12:12:00.Z</wsu:Created>
         </wsse:UsernameToken>
      </wsse:Security>
   </soapenv:Header>
   <soapenv:Body>
      <web:creerDevise>
         <!--Optional:-->
         <libelle>Livre</libelle>
      </web:creerDevise>
   </soapenv:Body>
</soapenv:Envelope>

From SOAPUI when I execute this request, I receive the following error:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <soap:Fault>
         <faultcode xmlns:ns1="http://ws.apache.org/wss4j">ns1:SecurityError</faultcode>
         <faultstring>A security error was encountered when verifying the message</faultstring>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>

So, I'm going to look at the wildfly logs where I have deployed the .ear archive of my app; And there I saw this exception:

Caused by: org.apache.wss4j.common.ext.WSSecurityException: The message has expired

Please help me to fix it, i am very new in ws-security. I don't know how can i resolve this exception.

FiokoSoft
  • 67
  • 1
  • 10
  • Are the server and the client in the same machine? Are the clocks synchronized? – pedrofb Dec 07 '16 at 21:02
  • @pedrofb, yes the server and client are the same machine. the server is Wildfly, it is installed on localhost and the client is SoapUI installed on same machine – FiokoSoft Dec 08 '16 at 05:11

1 Answers1

1

WSS4J enforces a time limit of 5 minutes by default on the Creation timestamp of a UsernameToken. So in SOAP UI you'll need to recreate the UsernameToken snippet if more than 5 minutes have elapsed since you last created it. Alternatively, you can configure WSS4J to allow a longer time limit for expiry.

Colm O hEigeartaigh
  • 1,882
  • 1
  • 12
  • 7
  • Thank you @Colm, how can i configure wss4j like this? – FiokoSoft Dec 08 '16 at 10:47
  • Thank you @Colm, how can i configure wss4j like this? And the time limit of 5 minutes correspond to which time interval? Because, i write the datetime of creation(element of ) by hand. I am very new in this technology, please can you explain to me more deeply, if possible with an example... – FiokoSoft Dec 08 '16 at 10:56
  • 1
    Why do you want to disable the expiry time limit? If you really have to, you can set the property "utTimeToLive" to some large value (defaults to "300" which is the time in seconds). 5 minutes is the time after the Created time in the UsernameToken where the receiver deems the message to have expired. – Colm O hEigeartaigh Dec 08 '16 at 12:21
  • Documentation (albeit a messy one) containing all _WSS4J_'s properties can be found here: https://ws.apache.org/wss4j/config.html. – Yuri Feb 08 '18 at 18:57