Recently, I've had the need to setup user authentication with webcenter and noticed that weblogic had it's own built in LDAP server. I didn't find my information around on the OTN or google about it so I thought I'd share what I learnt. Below is how to setup LDAP on a WLS and authenticate against it in Java.
Setting up Embedded LDAP on the Intergrated WLS
You will need to set the credential and confirm credential to a new password and check the Anonymous Bind Allowed check box. In this example we will use “welcome1”.
All the below methods can be used to interface with the WLS Embedded LDAP.
If you need to explore the WLS embedded LDAP directory structure you can download JXpolrer and use the following details.
Localhost Details:
Host: 127.0.0.1:7101
Base DN: dn=DefaultDomain
User DN: cn=Admin
Password: welcome1
Variables
private String ldapServer = "ldap://127.0.0.1:7101";
private String ldapPassword = "welcome1";
private String ldapDC = "DefaultDomain";
Change Password
public String changePassword(String username, String oldPassword,
String newPassword, String confirmNewPassword) {
if (oldPassword.equals(newPassword)) {
System.out.println("new and old passwords match");
return "Your new password must be different from your old password.";
}
if (!newPassword.equals(confirmNewPassword)) {
System.out.println("new password and confirmed password don't match");
return "Your new password must match your confirmed password.";
}
if (!isAuthenticated(username, oldPassword)) {
System.out.println("old password was not authenticated");
return "Your old password is incorrect.";
}
String ldapUri = ldapServer;
String admindn = "cn=Admin";
String admincred = ldapPassword;
String usersContainer = "ou=people,ou=myrealm,dc=" + ldapDC;
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 {
InitialDirContext initialContext = new InitialDirContext(env);
DirContext ctx = initialContext;
ModificationItem[] mods = new ModificationItem[1];
Attribute mod0 = new BasicAttribute("userpassword", newPassword);
mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, mod0);
ctx.modifyAttributes("uid=" + username + "," + usersContainer,
mods);
ctx.close();
return "Password Changed!";
} catch (NamingException e) {
System.out.println(e);
return "Woops! Something went wrong!";
}
}
Create User
public String createUser(String firstname, String lastname,
String username, String password,
String confirmPassword) {
if (!password.equals(confirmPassword)) {
return "Passwords do not match.";
}
String ldapUri = ldapServer;
String admindn = "cn=Admin";
String admincred = ldapPassword;
String usersContainer = "ou=people,ou=myrealm,dc=" + ldapDC;
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");
objclass.add("wlsuser");
Attribute surname = new BasicAttribute("sn");
surname.add(lastname);
Attribute givenname = new BasicAttribute("givenname");
givenname.add(firstname);
Attribute cn = new BasicAttribute("cn");
cn.add(username);
Attribute mail = new BasicAttribute("mail");
mail.add(username);
Attribute name = new BasicAttribute("displayname");
name.add(firstname + " " + lastname);
Attribute pwd = new BasicAttribute("userpassword");
pwd.add(password);
attrs.put(objclass);
attrs.put(mail);
attrs.put(givenname);
attrs.put(name);
attrs.put(cn);
attrs.put(surname);
attrs.put(pwd);
ctx.createSubcontext("uid=" + username + "," + usersContainer,
attrs);
ctx.close();
return "success";
} catch (NameAlreadyBoundException e) {
System.out.println(e);
return "User already exists.";
} catch (NamingException e) {
System.out.println(e);
return "Woops! Something went wrong!";
}
}
Reset Password
public String resetPassword(String username) {
SecureRandom random = new SecureRandom();
String randomString = new BigInteger(130, random).toString(32);
String newPassword = randomString.substring(0, 8);
String ldapUri = ldapServer;
String admindn = "cn=Admin";
String admincred = ldapPassword;
String usersContainer = "ou=people,ou=myrealm,dc=" + ldapDC;
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 {
InitialDirContext initialContext = new InitialDirContext(env);
DirContext ctx = initialContext;
ModificationItem[] mods = new ModificationItem[1];
Attribute mod0 = new BasicAttribute("userpassword", newPassword);
mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, mod0);
ctx.modifyAttributes("uid=" + username + "," + usersContainer,
mods);
ctx.close();
return newPassword;
} catch (NamingException e) {
System.out.println(e);
return "";
}
}
Check Authenticated
public boolean isAuthenticated(String username, String password) {
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapServer);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "uid=" + username + ",ou=people,ou=myrealm,dc=" + ldapDC);
env.put(Context.SECURITY_CREDENTIALS, password);
try{
DirContext ctx = new InitialDirContext(env);
String authorised = ctx.AUTHORITATIVE;
ctx.close();
return true;
}catch(NamingException e){
System.out.println(e);
return false;
}
}
Nice post.
ReplyDeleteI am getting javax.naming.NamingException: Cannot parse url: 127.0.0.1:7101. What could be the prob.
Hi Gopinath,
DeleteTry using "ldap://127.0.0.1:7101" instead of "127.0.0.1:7101".
Aaron
Hi Gopinath,
ReplyDeleteA NamingException could be a few things.
1) WLS is running on 7101 and on your localhost.
2) WLS domain is called DefaultDomain.
3) WLS username and password are correct.
In which method are you getting the error?
More then likely it is something to do with your LDAP details. Try connecting to the WLS using JXplorer to verify they're correct.
ReplyDeletei tried implementing this post got the below error
ReplyDeletejavax.naming.NamingException: Cannot parse url: 127.0.0.1:7101 [Root exception is java.net.MalformedURLException: Not an LDAP URL: 127.0.0.1:7101]
but iam able to connect with jexplorer
Hi Vidya,
DeleteTry setting the ldapServer variable to ldap://127.0.0.1:7101 instead of 127.0.0.1:7101 I accidentally deleted it when making the post. I have modified the above code to reflect this.
Aaron
My application connects to an external LDAP. What is the best way to allow the user to change the password through the application ? Do I use the weblogic security APIs or do I have to talk to the external LDAP through some other API ?
ReplyDeleteJaseer,
DeleteI would personally connect the weblogic to your external LDAP server and use the weblogic security APIs to update your user passwords or you could directly update your external LDAP server. However the former option provides you with the ability to change your LDAP servers without having to modify your application.
Aaron
Hi Aaron
ReplyDeleteIm getting the following error when using cn=Admin in weblogic 12.2.1.3:
javax.naming.AuthenticationException: [LDAP: error code 49 - Invalid Credentials]
With JXplorer I can connect,with optional base dn: dc=DefaultDomain
How can this be accomplished in the code?
I tried changing the ldapUrl to ldap://127.0.0.1:7101/dc=DefaultDomain but no luck
Any other ideas?
Btw: authenticating in the isAuthorized method does work, it only doenst for the cn=Admin
Thanks
Jirka