0

I made a WSS4JInInterceptor in a spring bean configuration file as follows

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
        xmlns:jaxrs="http://cxf.apache.org/jaxrs"
        xsi:schemaLocation="http://cxf.apache.org/jaxws 
                            http://cxf.apache.org/schemas/jaxws.xsd
                            http://www.springframework.org/schema/beans 
                            http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://cxf.apache.org/jaxrs 
                            http://cxf.apache.org/schemas/jaxrs.xsd">

        <jaxws:endpoint id="book"
            implementor="net.ma.soap.ws.endpoints.IBookEndPointImpl" address="/bookAuth">
            <jaxws:inInterceptors>
                <bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor"></bean>
                <bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
                    <constructor-arg>
                        <map>
                            <entry key="action" value="UsernameToken" />
                            <entry key="passwordType" value="PasswordText" />
                            <entry key="passwordCallbackClass" value="net.ma.soap.ws.service.ServerPasswordCallback"></entry>
                        </map>
                    </constructor-arg>
                </bean>
            </jaxws:inInterceptors>
        </jaxws:endpoint>
    </beans>

The ServerPasswordCallBack.java looks like the following

    package net.ma.soap.ws.service;

    import java.io.IOException;
    import java.util.ResourceBundle;
    import javax.security.auth.callback.Callback;
    import javax.security.auth.callback.CallbackHandler;
    import javax.security.auth.callback.UnsupportedCallbackException;
    import org.apache.wss4j.common.ext.WSPasswordCallback;

    public class ServerPasswordCallback implements CallbackHandler {

        private static final String BUNDLE_LOCATION = "zuth";
        private static final String PASSWORD_PROPERTY_NAME = "auth.manager.password";
        private static String password;

        static {
            final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_LOCATION);
            password = bundle.getString(PASSWORD_PROPERTY_NAME);
        }

        @Override
        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
            WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
            pc.setPassword(password);
        }
    }

With the password verification, everything work just fine.

I'd like to know if there's any other way to enhance the handle(Callback) method to make it more sophisticated so it would be able to check more than just one parameter, for example if i can make it check an access token, it would be much more better.

the password property is defined in zuth_fr_FR.properties file as follows

auth.manager.password=najah

Soufiane Rabii
  • 427
  • 2
  • 8
  • 29
  • WSPasswordCallback has a method getIdentifier() which gets you the value of the username from the security header. – Frank May 04 '16 at 07:32
  • Is this the only option to make a more sophisticated authentication ? – Soufiane Rabii May 04 '16 at 08:12
  • 1
    As far as I know yes. But with using the password as digest and other features of WS-Security like signature and encryption (Best done with WS-Policy or CryptoCoverageChecker to avoid signature wrapping attacks) it should be sufficient. By the way: storing a passwort as plaintext in a propertiesfile may not the safest way to avoid unauthorized access. ;-) – Frank May 04 '16 at 08:22
  • @Frank, What do you suggest as strategy of password storage? and what do you have anything that shows how to implement the features of WS-Security like **signature** and **encryption** **WS-Policy** ? – Soufiane Rabii May 04 '16 at 08:36
  • Regarding the password I recommend to read the [spec](https://www.oasis-open.org/committees/download.php/13392/wss-v1.1-spec-pr-UsernameTokenProfile-01.htm#_Toc104276210). A simple example of implementing encryption with cxf can be found on their site [http://cxf.apache.org/docs/ws-security.html](http://cxf.apache.org/docs/ws-security.html) – Frank May 04 '16 at 08:52
  • Thank you @Frank so much. I appreciate it. – Soufiane Rabii May 04 '16 at 08:58

1 Answers1

1

If you want to do some custom validation on your username and token (such as verify against a directoryservice using LDAP or something similar) you can write your own custom UsernameTokenValidator overriding verifyPlaintextPassword(UsernameToken usernameToken) of UsernameTokenValidator and hook it up to your WSS4JInInterceptor adding the following to your bean definition

<property name="wssConfig">
        <ref bean="usernameTokenWssConfig"/>
</property>

And add the referenced class to your codebase:

@Component("usernameTokenWssConfig")
public class usernameTokenWssConfigWSSConfig {
    public usernameTokenWssConfig() {
        setValidator(WSSecurityEngine.USERNAME_TOKEN, new CustomUsernameTokenValidator());
        setRequiredPasswordType(WSConstants.PASSWORD_TEXT);
    }
}
Frank
  • 2,036
  • 1
  • 20
  • 32