Using the steps below I was able to improve upon the integration between IDempiere and OpenDJ. Specifically, I worked on the LDAP based login feature of IDempiere. I was able to improve LDAP integration between IDempiere and OpenDJ such that using the steps below a user is able to login via his LDAP user-name and password irrespective of where his account exists in the LDAP directory structure.
When a user attempts to login to IDempiere an LDAP search takes place on the integrated OpenDJ instance. Once the user-name is found as a result of the search, in the second step the password token is authenticated.
The OpenDJ UID field is mapped to the user-name on the IDempiere Login screen. An LDAP password associated with the UID field must also be pre-entered in IDempiere. However, this password can be a dummy value.
The steps below assume that your development environment for IDempiere is already set-up.
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved.
* This program is free software; you can redistribute it and/or modify it
* under the terms version 2 of the GNU General Public License as published
* by the Free Software Foundation. This program is distributed in the hope
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
* You may reach us at: ComPiere, Inc. – http://www.compiere.org/license.html
* 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA or info@compiere.org
*****************************************************************************/
package org.compiere.db;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.compiere.util.CLogger;
/**
* LDAP Management Interface
*
* @author Jorg Janke
* @version $Id: LDAP.java,v 1.2 2006/07/30 00:55:13 jjanke Exp $
* @modified Faraz Haider
*/
public class LDAP {
private static String getUid(String ldapURL, String user) throws Exception {
DirContext ctx = null;
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY,
“com.sun.jndi.ldap.LdapCtxFactory”);
env.put(Context.PROVIDER_URL, ldapURL);
try {
ctx = new InitialDirContext(env);
} catch (NamingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String filter = “(uid=” + user + “)”;
SearchControls ctrl = new SearchControls();
ctrl.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration answer = ctx.search(“”, filter, ctrl);
String dn;
if (answer.hasMore()) {
SearchResult result = (SearchResult) answer.next();
dn = result.getNameInNamespace();
} else {
dn = null;
}
answer.close();
return dn;
}
private static boolean testBind(String ldapURL, String dn, String password)
throws Exception {
DirContext ctx = null;
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY,
“com.sun.jndi.ldap.LdapCtxFactory”);
env.put(Context.PROVIDER_URL, ldapURL);
env.put(Context.SECURITY_AUTHENTICATION, “simple”);
env.put(Context.SECURITY_PRINCIPAL, dn);
env.put(Context.SECURITY_CREDENTIALS, password);
try {
ctx = new InitialDirContext(env);
} catch (javax.naming.AuthenticationException e) {
return false;
}
return true;
}
/**
* Validate User
*
* @param ldapURL
* provider url – e.g. ldap://dc.compiere.org
* @param domain
* domain name = e.g. compiere.org
* @param userName
* user name – e.g. jjanke
* @param password
* password
* @return true if validated with ldap
*/
public static boolean validate(String ldapURL, String domain,
String userName, String password) {
String dn = null;
try {
dn = getUid( ldapURL, userName );
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (dn != null) {
/* Found user – test password */
try {
if ( testBind( ldapURL, dn, password ) ) {
log.info(“OK: ” + userName);
return true;
}
else {
log.severe(“Authentication failed for user: ‘” + userName + “‘” );
return false;
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//else {
log.severe(“User: ‘” + userName + “‘ not found.” );
return false;
//}
} // validate
/** Logger */
private static CLogger log = CLogger.getCLogger(LDAP.class);
/**
* Test NT
*
* @throws LoginException
*
* private static void testNT () throws LoginException { try {
* System.out.println
* (“NT system —————————-“); NTSystem ntsystem
* = new NTSystem (); System.out.println (ntsystem);
* System.out.println (ntsystem.getDomain ());
* System.out.println (ntsystem.getDomainSID ());
* System.out.println (ntsystem.getName ()); System.out.println
* (ntsystem.getUserSID ()); System.out.println
* (“NT login —————————-“); NTLoginModule
* ntlogin = new NTLoginModule (); System.out.println (ntlogin);
* Map<String,String> map = new HashMap<String,String>();
* map.put (“debug”, “true”); ntlogin.initialize (null, null,
* null, map); System.out.println (ntlogin.login ()); } catch
* (LoginException le) { System.err.println
* (“Authentication attempt failed” + le); } } // testNT
*
*
* /** testKerberos
* @throws LoginException
*
* private static void testKerberos () throws LoginException {
* System.out.println
* (“Krb login —————————-“);
* Map<String,String> map = new HashMap<String,String>(); //
* map.put(“debug”, “true”); // map.put(“debugNative”, “true”);
* Krb5LoginModule klogin = new Krb5LoginModule ();
* System.out.println (klogin); map.put (“principal”,
* “username@compiere.org”); map.put (“credential”, “pass”);
* klogin.initialize (null, null, null, map); System.out.println
* (klogin.login ());
* /******************************************
* ***************************** ** No krb5.ini file found in
* entire system Debug is true storeKey false useTicketCache
* false useKeyTab false doNotPrompt false ticketCache is null
* KeyTab is null refreshKrb5Config is false principal is jjanke
* tryFirstPass is false useFirstPass is false storePass is
* false clearPass is false [Krb5LoginModule] authentication
* failed Could not load configuration file c:\winnt\krb5.ini
* (The system cannot find the file specified)
* javax.security.auth.login.LoginException: Could not load
* configuration file c:\winnt\krb5.ini (The system cannot find
* the file specified)
*
* } // testKerbos /
**/
/**
* Print Attributes to System.out
*
* @param attrs
*/
@SuppressWarnings(“unused”)
private static void dump(Attributes attrs) {
if (attrs == null) {
System.out.println(“No attributes”);
} else {
/* Print each attribute */
try {
for (NamingEnumeration<? extends Attribute> ae = attrs.getAll(); ae
.hasMore();) {
Attribute attr = ae.next();
System.out.println(“attribute: ” + attr.getID());
/* print each value */
for (NamingEnumeration<?> e = attr.getAll(); e.hasMore(); System.out
.println(” value: ” + e.next()))
;
}
} catch (NamingException e) {
e.printStackTrace();
}
}
} // dump
/**
* Test
*
* @param args
* ignored
*/
public static void main(String[] args) {
try {
validate(“ldap://directory.my.company.pk”, “dc=my,dc=company,dc=pk”, “faraz”,
“ikeepforgetting”);
} catch (Exception e) {
e.printStackTrace();
}
} // main
} // LDAP