Friday, December 28, 2012

Plain-text Passwords based Authentication change in WSS4J 1.6+

I was going through the tutorial in [1] using plain-text passwords for UsernameToken authentication via a policy. (A deprecated method for this type of authentication without a policy is explained in this post). In Axis2, WS-Security aspects are handled by Rampart module by using WSS4J as the provider. I used the version 1.6.4 of it, which comes bundled with Rampart 1.6.2.

Ideal mechanism of plain-text passwords based authentication is, when Rampart receives the request, it should handover the username and the password to the call back handler that user writes. This handler will use its specific authentication mechanism (or delegate to an authentication component/system) to compare this plain-text password with a stored password which will be most probably in an encrypted form. Simply, the responsibility of authentication should be user's.

However, things didn't work according to the tutorial; authentication started to fail.

Debugging WSS4J took me inside UsernameTokenValidator class, which didn't exist prior to 1.6. I found out that even though client sends the password in plain-text, by default WSS4J will do the validation the digest-password way. i.e verifyPlaintextPassword() in that class simply calls verifyDigestPassword(). So, it always sends a null value to the password callback handler and the user is supposed to provide a plain-text password to Rampart. This is not the ideal mechanism.

Then I found [2] where it explains that starting from WSS4J 1.6, UsernameToken processing architecture has been modified. By default it no longer handles the plain-text passwords the old way. Validations are not hard wired to UsernameTokenProcessor, which was the case prior to WSS4J 1.6. Validators such as UsernameTokenValidator - which is the default validator - should be custom written.

So, if we want the ideal behaviour we talked, we must write a custom validator, in which we should @Override verifyPlaintextPassword() with the implementation we prefer and plug that validator to the UsernameTokenProcessor instead of the default UsernameTokenValidator.

Rational behind this architectural change can be read in [2].


1 comment:

Ronnie Kilsbo said...

Thanks for the clarification.

Do you have any examples or links to examples how to implement usch a Validator and how to hook it up to a rampart security configuration in a service.xml for a service?

Been googling about this for quite some time now without finding anyone describing how to actually do this.

Best Regards,