In the latest release version, 1.5.8, you will need to implement 
javax.security.auth.callback.CallbackHandler and provide that to WSS4J as a 
property keyed by WSHandlerConstants#PW_CALLBACK_CLASS or 
WSHandlerConstants#PW_CALLBACK_REF.  See the JavaDoc on each for more details.  
I think some finer details of the callback handler usage are changing in 1.6 so 
please review what I say against the actual WSS4J code.

 

You will implement the CallbackHandler interface’s handle method.  The array of 
callbacks should contain instance(s) of 
org.apache.ws.security.WSPasswordCallback.  This class has a field called 
usage.  This field indicates what the callback wants your handler to do.  See 
the JavaDoc for the class for complete details of each usage.  For the case of 
a username token, the usages can be either: 

1)      WSPasswordCallback#USERNAME_TOKEN - This usage occurs on outbound 
requests using a UserNameToken and on validation of inbound requests using a 
UserNameToken with a digest password format.  The caller expects the 
implementation to set the password field of the callback 
(WSPasswordCallback#setPassword(String)).

2)      WSPasswordCallback#USERNAME_TOKEN_UNKNOWN - Handle a request to 
validate a plain text password or a custom password type for the username.

 

To perform validation of the password, I would recommend looking into Spring 
Security [1]  as it has great integration with LDAP and many other identity 
management systems.  Alternatively, you could look into using LdapLoginModule 
[2].

 

Now on to your second issue, hashed passwords and the plain-text passwords.  
The WS-Security Username Token Profile [3] lets you use plain text passwords in 
your messages or digest passwords in your messages.  If you use plain text 
passwords, you will of course need to obfuscate the username token, protect the 
token from theft and alteration (encryption of token or message and integrity 
constraining of token or message), and protect against attackers replaying the 
token (created time and nonce).  The plus side to plain text passwords is that 
your server side authentication logic will work just fine with LDAP.  Your 
callback handler supplies the user’s plain text password to LDAP and LDAP 
authenticates the value by hashing it with the secret salt and comparing it to 
the stored value.  If you use digest passwords, you get a little bit more 
protection of the password in transit, but hashing should not be considered as 
secure as encrypting.  You still need to protect against theft and alteration 
of the token, replay of the token, and you should still consider the hashed 
password as vulnerable to offline brute force attacks.  The other downside to 
digested passwords is that the server needs access to the user’s plain text 
password to validate the digest.  In most cases, an identity management 
solution isn’t going to have a plain text copy of the user’s password laying 
around, and if they do, they aren’t likely to just hand it over to your server. 
 There is the idea of a password equivalent that one can use in lieu of the 
true password.  For instance, instead of creating the digest with the plain 
text password, the client creates the digest with a hash of their plain text 
password.  In this case, the server would still need to know the user’s 
password equivalent in order to validate the digest.  As an attacker could 
still brute force the password equivalent, it is not immune from theft.  Since 
the equivalent is just as good as the original password in this scenario, the 
attacker then knows the user’s password equivalent and can access the system.  
The only thing a password equivalent really buys you is prevention of exposure 
of the user’s plain text password, but this could still be brute forced from 
the password equivalent.  You are basically just adding a delay to the attack.

 

[1] 
http://static.springsource.org/spring-security/site/docs/3.1.x/reference/ldap.html

[2] 
http://download.oracle.com/javase/6/docs/jre/api/security/jaas/spec/com/sun/security/auth/module/LdapLoginModule.html

[3] 
http://docs.oasis-open.org/wss/v1.1/wss-v1.1-spec-os-UsernameTokenProfile.pdf

 

 

David Valeri

---------------------------

http://davidvaleri.wordpress.com/

http://twitter.com/DavidValeri

 

From: José CARRENO [mailto:jjb.carr...@gmail.com] 
Sent: Wednesday, September 08, 2010 6:00 AM
To: wss4j-dev@ws.apache.org
Subject: Securing Web Service withLDAP

 

Hello,


I'm a bit new to WSS4J and i'm sure this question has already been asked in the 
past but i haven't got see any clear answer yet, so i hope you'll help me:

We'd like to secure our Web Service using WSS4J against our LDAP Directory. 
From what i read about wss4j, each part (client and server side) have to 
implement a CallbackHandler that provide a username / password pair. Then some 
comparisons are performed on those tokens to see if client and server match. 
How can we do that with LDAP ?

Let me take this example to explain : In LDAP we have user Bob with password 
BobPwd. This BobPwd is stored in ldap as something like  
{SSHA}9849840sd984a0d... So, on the server side, i can't get original password 
and therefore i have no way to make comparison. The only solution would be that 
client provides the SHA encrypted password but I find it not a very pleasant 
workaround and i feel i'm missing something...

QUESTION 1 : Which class is responsible for comparing client and server tokens 
in WSS4J ?

QUESTION 2 : What is the best way to secure a Web service against ldap knowing 
that LDAP password are SHA encoded using a salt that we can't know ?

QUESTION 3 : I saw that Spring-WS provides an implementation to secure a 
Webservice against LDAP 
(http://www.techinfopad.com/spring/101202782-using-roles-in-ldap-with-springws.html).
 How do they do that ? 

Thank you very much for your help ! 

Jose

 

Reply via email to