Retrieve data from active directory - java

I am developing a project in java and JSP that needs to access an active directory for login and retrieving some values. I have done the login part(authentication) but i am not able to get help over the retrieval part.I am completely new to active directory concept, so please aid me accordingly.
I am giving the code of the java class that i have used for user authentication:
package classes;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
public class AD_Auth {
private static final String CONTEXT_FACTORY_CLASS ="com.sun.jndi.ldap.LdapCtxFactory";
private static final String domainName = "#xyz.IN";
private static final String providerUrl = "ldap://srdeladc02.xyz.in:123";
public static boolean authenticate(String username, String password) {
try {
Hashtable<Object, Object> env = new Hashtable<Object, Object>();
env.put(Context.INITIAL_CONTEXT_FACTORY, CONTEXT_FACTORY_CLASS);
env.put(Context.PROVIDER_URL, providerUrl);
env.put(Context.SECURITY_PRINCIPAL, username + domainName);
env.put(Context.SECURITY_CREDENTIALS, password);
env.put(Context.SECURITY_AUTHENTICATION, "strong");
DirContext ctx = new InitialDirContext(env);
ctx.close();
return true;
} catch (NamingException e) {
System.out.println("Dear User, The username or password you have entered is in correct, please try again.");
}
return false;
}
public static void main(String[] args) {
// if someone emailid is myemail#icar.gov.in then username will be myemail
//System.out.println(AD_Auth.authenticate("username", "password"));
}
}

Related

Issues with adding user to LDAP server in Java using JNDI

I'm having an issue with adding a user to my LDAP server in Java.
Here's what my code looks like
import java.util.Hashtable;
import java.util.Properties;
import java.util.jar.Attributes;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
public class LdapProgram {
public static void main(String[] args) {
String dn = "";
String password = "";
Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
properties.put(Context.PROVIDER_URL, "ldap://127.0.0.1");
properties.put(Context.SECURITY_AUTHENTICATION,"none");
properties.put(Context.SECURITY_PRINCIPAL,password);
properties.put(Context.SECURITY_CREDENTIALS,dn);
// TODO code application logic here
// entry's DN
String entryDN = "uid=test_user,ou=people,dc=test123,dc=com";
// entry's attributes
Attribute cn = new BasicAttribute("cn", "tester");
Attribute uid = new BasicAttribute("uid", "tester");
Attribute gecos = new BasicAttribute("gecos", "test");
Attribute oc = new BasicAttribute("objectClass");
oc.add("top");
oc.add("person");
oc.add("organizationalPerson");
oc.add("inetOrgPerson");
DirContext ctx = null;
try {
// get a handle to an Initial DirContext
ctx = new InitialDirContext(properties);
// build the entry
BasicAttributes entry = new BasicAttributes();
entry.put(cn);
entry.put(uid);
entry.put(gecos);
entry.put(oc);
// Add the entry
ctx.createSubcontext(entryDN, entry);
// System.out.println( "AddUser: added entry " + entryDN + ".");
} catch (NamingException e) {
System.err.println("AddUser: error adding entry.\n" + e);
}
}
}
Here is the error code I get: javax.naming.AuthenticationNotSupportedException: [LDAP: error code 8 - modifications require authentication]; remaining name 'uid=test_user,ou=people,dc=test123,dc=com'
I'm not understanding why it's saying it requires authentication when I'm already binded to the server with the admin user and password.

A way to define / implement failover ldap servers in java code

I have the following code for Ldap user authentication:
import java.util.Hashtable;
import javax.naming.*;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
public class LdapUtil {
public static final String PROVIDER_URL= "ldap://ourLdapServer";
public static final String SECURITY_AUTHENTICATION="simple";
public static final String SECURITY_PRINCIPAL_POSTFIX="#org.local";
private String ldapAttributes[] = null;
public boolean isCorrectUser(String user, String pass){
boolean result = false;
if (user == null || pass == null || "".equals(user) || "".equals(pass)) {
return result;
}
try {
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, PROVIDER_URL);
env.put(Context.SECURITY_AUTHENTICATION, SECURITY_AUTHENTICATION);
env.put(Context.SECURITY_PRINCIPAL, user + SECURITY_PRINCIPAL_POSTFIX);
env.put(Context.SECURITY_CREDENTIALS, pass);
LdapContext ctxGC = new InitialLdapContext(env, null);
ldapAttributes = getUserBasicAttributes(user,ctxGC);
ctxGC.close();
result = true;
//System.out.println("LDAP authentication for " + username + " succeeded!");
} catch (Exception e) {
// Not authenticated
result = false;
//System.out.println("LDAP authentication for " + username + " failed!");
}
return result;
}
}
There is one main drawback - it works only for one Ldap server.
Now I would like to define alternative Ldap servers for fail-over purposes (e.g. when the main ldap is down or is not accessible - the program should try to query the secondary ldap, if that is not available next one etc.).
How would I achieve that?
And how would I minimise authentication time if the primary server would stay offline for a long time?
Thanks in advance.
Just add multiple LDAP PROVIDER_URLs:
// Specify list of [space-separated URL][1]s
env.put(Context.PROVIDER_URL,
"ldap://ourLdapServer " +
"ldap://ourLdapServer2 " +
"ldap://ourLdapServer3 " +
"ldap://ourLdapServer4");

List all the users in the Active Directory Group

I am facing some difficulties while listing all the users in the Active Directory. I reached to the group, but unfortunately, I could not retrieve all the users. I am looking for the user Full Names, usernames, directorate. My code is:
package client;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import javax.naming.ldap.*;
import java.util.Enumeration;
import javax.naming.NamingEnumeration;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.directory.*;
public class AD1 {
public AD1() {
super();
}
public static String usersContainer = "cn=XX,ou=XX,ou=Groups,dc=XX,dc=XX,dc=XXX";
public static void main(String[] args) {
try {
LdapContext ctx = null;
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION, "Simple");
//it can be <domain\\userid> something that you use for windows login
//it can also be
env.put(Context.SECURITY_PRINCIPAL, "username");
// env.put(Context.SECURITY_CREDENTIALS, "password");
try {
env.put(Context.SECURITY_CREDENTIALS, "password".getBytes("UTF8"));
}
catch (java.io.UnsupportedEncodingException e) { /* ignore */ }
//in following property we specify ldap protocol and connection url.
//generally the port is 389
env.put(Context.PROVIDER_URL, "ldap://IP:PORT");
ctx = new InitialLdapContext(env, null);
System.out.println("Connection Successful.");
DirContext ctx1 = new InitialDirContext(env);
SearchControls ctls = new SearchControls();
String[] attrIDs = { "distinguishedName","cn","name","uid",
"sn",
"givenname",
"memberOf",
"samaccountname",
"userPrincipalName" };
ctls.setReturningAttributes(attrIDs);
ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
//ctls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
NamingEnumeration answer = ctx1.search( usersContainer, "(objectClass=user)", ctls );
System.out.print("Out while loop");
while(answer.hasMore()) {
System.out.print("while loop11");
SearchResult rslt = (SearchResult)answer.next();
Attributes attrs = rslt.getAttributes();
System.out.println(attrs.get("uid"));
ctx1.close();
}
} catch(NamingException nex) {
System.out.println("Active Directory Connection: FAILED");
nex.printStackTrace();
}
}
}
Can anyone help.
As it's active directory and not real ldap your talking about, can you help us with more details about ldap/active directory configuration ?
It's kind hard to help you with informations you give
Edit 1:
your problem is here no ?
while(answer.hasMore()) {
System.out.print("while loop11");
SearchResult rslt = (SearchResult)answer.next();
Attributes attrs = rslt.getAttributes();
//System.out.println(attrs.get("uid"));
System.out.println(attrs.get("cn"));
ctx1.close();
}

How to programmatically add user account to openDS?

I need to add some user accounts to a openDS server programmatically, but I don't know how to do it even after look through the openDS wiki. Could anyone help me?
The below code is using jndi. This will just add an user object with provided password. This is not much. But this might help you to get started.
Also I would prefer to stick with jndi compared to opends-sdk.
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.DirContext;
import javax.naming.directory.Attributes;
import javax.naming.directory.Attribute;
import javax.naming.NamingException;
public class App {
/* Ugly HardCoded stuff */
public static String ldapUri = "ldap://localhost:2389";
public static String admindn = "cn=Directory Manager";
public static String admincred = "password";
public static String usersContainer = "ou=users,dc=example,dc=com";
public static void main(String args[]){
if (args.length != 2) {
System.out.println("Usage: App userName password");
return;
}
String username = args[0];
String password = args[1];
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapUri);
env.put( Context.SECURITY_PRINCIPAL, admindn );
env.put( Context.SECURITY_CREDENTIALS, admincred );
try {
DirContext ctx = new InitialDirContext(env);
Attributes attrs = new BasicAttributes(true);
Attribute objclass = new BasicAttribute("objectclass");
objclass.add("top");
objclass.add("inetorgperson");
Attribute surname = new BasicAttribute("sn");
surname.add(username);
Attribute pwd = new BasicAttribute("userpassword");
pwd.add(password);
attrs.put(objclass);
attrs.put(surname);
attrs.put(pwd);
ctx.createSubcontext("cn="+username+","+usersContainer, attrs);
ctx.close();
} catch (NamingException e) {
e.printStackTrace();
}
}
}
To add programmatically user accounts in OpenDS, you need to use an LDAP client library for your OS and preferred programming language.
OpenDS has an LDAP library for Java, with many sample code.
http://www.opends.org/promoted-builds/sdk/20110126210001/
Sample are in the Example directory.
Here the code used in php working fine for me
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
</head>
<body>
<?php
$ldapconfig['host'] = 'PC100';
$ldapconfig['port'] = 1389;
$ldapconfig['basedn'] = 'dc=company,dc=com';
$ds=ldap_connect($ldapconfig['host'], $ldapconfig['port']);
$password=1;
$username="cn=Directory Manager";
if ($bind=ldap_bind($ds, $username, $password)) {
echo("Login correct");
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3); // IMPORTANT
$dn = "cn=roshanis,dc=example,dc=com";
$ldaprecord['cn'] = "roshanis";
$ldaprecord['givenName'] = "mkljl";
$ldaprecord['sn'] = "roshan";
$ldaprecord['objectclass'][0] = "inetOrgPerson";
$ldaprecord['objectclass'][1] = "test";
$ldaprecord['mail'] = "lkl#fh.com";
// add data to directory
$r = ldap_add($ds, $dn, $ldaprecord);
// $r= ldap_modify($ds, $dn, $ldaprecord);
} else {
echo("Unable to bind to server.</br>");
}
?>
</body>
</html>

Execute a script on remote server from a java application authenticating via kerberos keytabs

This has been most likely answered earlier, but all my searches did not get me a definite answer. What I've got is a Java application that currently uses ssh keys to run a script on a remote machine and save the results. I'm in the process of changing this to a Kerberos authentication using keytabs. I have the keytab set up and tested it using a perl script. If someone could point me to examples that tell me how to use kerberos keytabs in a Java application, that would be very helpful.
Thanks,
Kiran
Here's a full implementation of using a keytab in Java.
import javax.security.auth.Subject;
import javax.security.auth.kerberos.KerberosPrincipal;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import java.security.Principal;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
public class SecurityUtils {
public static class LoginConfig extends Configuration {
private String keyTabLocation;
private String servicePrincipalName;
private boolean debug;
public LoginConfig(String keyTabLocation, String servicePrincipalName, boolean debug) {
this.keyTabLocation = keyTabLocation;
this.servicePrincipalName = servicePrincipalName;
this.debug = debug;
}
#Override
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
HashMap<String, String> options = new HashMap<String, String>();
options.put("useKeyTab", "true");
options.put("keyTab", this.keyTabLocation);
options.put("principal", this.servicePrincipalName);
options.put("storeKey", "true");
options.put("doNotPrompt", "true");
if (this.debug) {
options.put("debug", "true");
}
options.put("isInitiator", "false");
return new AppConfigurationEntry[]{new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule",
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options),};
}
}
public static Subject loginAs(String keyTabLocation, String servicePrincipal) {
try {
LoginConfig loginConfig = new LoginConfig(keyTabLocation, servicePrincipal, true);
Set<Principal> princ = new HashSet<Principal>(1);
princ.add(new KerberosPrincipal(servicePrincipal));
Subject sub = new Subject(false, princ, new HashSet<Object>(), new HashSet<Object>());
LoginContext lc;
lc = new LoginContext("", sub, null, loginConfig);
lc.login();
return lc.getSubject();
} catch (LoginException e) {
e.printStackTrace();
}
return null;
}
}
The loginAs method will return you a Subject which can be used to execute a privileged action:
result = Subject.doAs(subject,
new PrivilegedExceptionAction<NamingEnumeration<SearchResult>>() {
public NamingEnumeration<SearchResult> run() throws NamingException {
return context.search(directoryBase, filterBuilder.toString(), searchCtls);
}
});

Categories