Ok I think I am getting a bit closer, now. If using plain password UT then I guess this will need to used over HTTPs, as transmitting plain text passwords over HTTP is a security risk. If the password type is password digest (a hashed password) then WSS4J UsernameTokenProcessor class processes the password completely If the password is of type password text or any other unknown password type UsernameTokenProcessor delegates the password validation to the callback class.
So if we want to use a hashed password UT, then we need to lookup the password from a store in my callbackhandler class and add this to the WSPasswordCallback object. Then the WSS4J UsernameTokenProcessor would perform hash algorithm and compare the result with the transmitted password. Herein lies a little issue. In the application I am working with the we do not store the password anywhere in its plain text form, and hence I cannot add it to the WSPasswordCallback object for it to be verfied by my PatientServiceValidateUserTokenHandler class. Am I correct in my understanding of how this stuff works, so far ? Thanks K ________________________________ From: Farmah, Kam [mailto:[EMAIL PROTECTED] Sent: Tuesday 19 June 2007 16:26 To: [email protected] Subject: [xfire-user] Ws-security UserToken Hashed Password Hi, I am new to xfire and I am trying to get ws-sec implemented using the supplied examples as the basis. I have a few questions regarding whether I am along the right lines, and also a few conceptual questions: Here is my config: <service> <name>PatientServiceUTHP</name> <namespace>http://ctms.perceptive.com/PatientServiceWss</namespace> <serviceClass>com.perceptive.ctms.service.PatientService</serviceClass> <implementationClass>com.perceptive.ctms.service.PatientServiceImpl</imp lementationClass> <inHandlers> <handler handlerClass="org.codehaus.xfire.util.dom.DOMInHandler" /> <bean class="org.codehaus.xfire.security.wss4j.WSS4JInHandler" xmlns=""> <property name="properties"> <props> <prop key="action">UsernameToken</prop> <prop key="passwordCallbackClass">com.perceptive.ctms.service.PatientServicePa sswordHandler</prop> </props> </property> </bean> <handler handlerClass="com.perceptive.ctms.service.PatientServiceValidateUserToke nHandler" /> </inHandlers> </service> My client is as follows (snippet): Service serviceModel = new ObjectServiceFactory().create(PatientService.class, "PatientService", PatientServiceClient.SERVICE_NAMESPACE, null); PatientService service = (PatientService) new XFireProxyFactory().create(serviceModel, PatientServiceClient.SERVICE_URL + serviceName); Client client = ((XFireProxy) Proxy.getInvocationHandler(service)).getClient(); client.addOutHandler(new DOMOutHandler()); Properties properties = new Properties(); configureOutProperties(properties); client.addOutHandler(new WSS4JOutHandler(properties)); System.out.print("Looking for list of patients...."); List patients = service.getByTrialUnit(269, "FRA", 1); The configureOutProperties() does the following: protected void configureOutProperties(Properties properties) { // Action to perform : user token properties.setProperty(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN); // Set password type to hashed properties.setProperty(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_DIGEST); // Username in keystore properties.setProperty(WSHandlerConstants.USER, "pdi"); // Used do retrive password for given user name properties.setProperty(WSHandlerConstants.PW_CALLBACK_CLASS, PatientServiceClientPasswordHandler.class.getName()); } Client Password Hander class: public class PatientServiceClientPasswordHandler implements CallbackHandler { private Map passwords = new HashMap(); public PatientServiceClientPasswordHandler() { passwords.put("pdi", "pdi"); } public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { WSPasswordCallback pc = (WSPasswordCallback) callbacks[0]; String id = pc.getIdentifer(); pc.setPassword((String) passwords.get(id)); } } Server Password Handler class(snippet): public class PatientServicePasswordHandler implements CallbackHandler { public PatientServicePasswordHandler() { } private String username; private String password; public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { try { WSPasswordCallback pc = (WSPasswordCallback)callbacks[0]; int usage = pc.getUsage(); //its plain text pwd if (usage == WSPasswordCallback.USERNAME_TOKEN_UNKNOWN) { username = pc.getIdentifer().toUpperCase(); password = pc.getPassword().toUpperCase(); } //its a hashed pwd if (usage == WSPasswordCallback.USERNAME_TOKEN) { username = pc.getIdentifer().toUpperCase(); .......... ........... My Validate class: public class PatientServiceValidateUserTokenHandler extends AbstractHandler { public void invoke(MessageContext context) throws Exception { Vector result = (Vector) context.getProperty(WSHandlerConstants.RECV_RESULTS); for (int i = 0; i < result.size(); i++) { WSHandlerResult res = (WSHandlerResult) result.get(i); for (int j = 0; j < res.getResults().size(); j++) { WSSecurityEngineResult secRes = (WSSecurityEngineResult) res.getResults().get(j); int action = secRes.getAction(); // USER TOKEN if( (action & WSConstants.UT )>0 ){ WSUsernameTokenPrincipal principal = (WSUsernameTokenPrincipal) secRes .getPrincipal(); // Set user property to user from UT to allow response encryption context.setProperty(WSHandlerConstants.ENCRYPTION_USER,principal.getName ()); System.out.print("User : " + principal.getName() + " password : " + principal.getPassword() + "\n"); } // SIGNATURE if( ( action & WSConstants.SIGN ) > 0 ){ X509Certificate cert = secRes.getCertificate(); X500Name principal = (X500Name) secRes.getPrincipal(); // Do something whith cert System.out.print("Signature for : " + principal.getCommonName()); } } } } } Here are my questions Is the callBack handler only applicable to the client, as a mechnism to prompt the user for a username/password pair? In my config I have a client callback class (PatientServiceClientPasswordHandler), and then another serverside callback class (PatientServicePasswordHandler) which is going to lookup the password from some kind of password serverside store. Is this correct ? I see the book store example uses it both client side (to add security to SOAP header), and serverside to provide the password lookup, so the example works OK. If this is correct then why when I try to use the PW_DIGEST is the password not available, like it is when I call PW_TEXT? Ie during validation the call to : Vector result = (Vector) context.getProperty(WSHandlerConstants.RECV_RESULTS); returns null. So what really is the purpose of the PatientServiceValidateUserTokenHandler ? I guess I don't quite understand the order of execution, so I desperatley need some help and guidance on my approach. Thanks in advance.. Kam
