Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WS-security (usernametoken) for CXF - encrypted passwords possible?

I'm trying to get together with CXF's WS-security implementation(usernametoken). I've done everything as said at http://cxf.apache.org/docs/ws-security.html. My PasswordCallbackHandler seems to be working, but what bothers me is a part:

    if (pc.getIdentifier().equals("joe")) {
        // set the password on the callback. This will be compared to the
        // password which was sent from the client.
        pc.setPassword("password");
    }

as said

Note that for up to and including CXF 2.3.x, the password validation of the special case of a plain-text password (or any other yet unknown password type) is delegated to the callback class, see org.apache.ws.security.processor.UsernameTokenProcessor#handleUsernameToken() method javadoc of the WSS4J project. In that case, the ServerPasswordCallback should be something like the following one:

so up to cxf 2.3.x it was done like that

   if (pc.getIdentifer().equals("joe") {
       if (!pc.getPassword().equals("password")) {
            throw new IOException("wrong password");
       }
    }

My issue is: I don't want to pc.setPassword("plainTextPassword") as I want to store it in any resource. This up-to-2.3.x design would allow me to do this since I could encrypt it manually. Are there any ways of setting encrypted password in callback or doing usernametoken authentication for stored, encrypted passwords ?

I'm using cxf 2.5.x

like image 779
Jan Avatar asked Jan 19 '12 12:01

Jan


People also ask

What does Apache CXF use for integration with WSS4J and security?

CXF relies on WSS4J in large part to implement WS-Security. Within your own services, WS-Security can be activated by using WS-SecurityPolicy, which provides a comprehensive and sophisticated validation of the security properties of a received message.

What is CXF used for?

Overview. Apache CXF™ is an open source services framework. CXF helps you build and develop services using frontend programming APIs, like JAX-WS and JAX-RS. These services can speak a variety of protocols such as SOAP, XML/HTTP, RESTful HTTP, or CORBA and work over a variety of transports such as HTTP, JMS or JBI.

What is WSS4JOutInterceptor?

Class WSS4JOutInterceptor Property name for a map of action IDs ( Integer ) to action class names.


2 Answers

The answer (which I've tried) is found in this blog page:

http://coheigea.blogspot.com/2011/06/custom-token-validation-in-apache-cxf.html

The essence is to create a subclass of org.apache.ws.security.validate.UsernameTokenValidator, and override the verifyPlaintextPassword method. In that method, the UsernameToken (which provides getName and getPassword) is passed. Throw an exception if they're not valid.

To install the custom validator in a spring configuration, add e.g.

  <jaxws:properties>
    <entry key="ws-security.ut.validator">
        <bean class="com.example.webservice.MyCustomUsernameTokenValidator" />
    </entry>
  </jaxws:properties>

into the <jaxws:endpoint/>.

like image 110
dmansfield Avatar answered Sep 25 '22 15:09

dmansfield


Callback Handlers are there to provide the plaintext password or verify a digest password where the plaintext password is known.

But if you don't know the plaintext i.e. its one way hashed, then the callback interface is not appropriate and you should create a class that implements the Validator interface.

Here is my example implementation of that interface that uses a JPA repository in which the password is already stored as a BCrypt hash.

Use with the ws-security.ut.validator property documented here

i.e. as a CXF property <entry key="ws-security.ut.validator" value-ref="com.package.CustomUsernameTokenValidator" />

public class CustomUsernameTokenValidator implements Validator {
    @Autowired
    ProfileRepository profileRepository;
    @Override
    public Credential validate(Credential credential, RequestData requestData) throws WSSecurityException {
        Profile profile = profileRepository.findByName(credential.getUsernametoken().getName());
        if (profile != null) {
            if (BCrypt.checkpw(credential.getUsernametoken().getPassword(), profile.getPassword())) {
                return credential;
            }
        }
        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);     
    }
}
like image 33
muttonUp Avatar answered Sep 28 '22 15:09

muttonUp