- Tech Corner
- Articles
- Oracle Tips
LDAP Authentication & Active Directory
Abstract
LDAP authentication
LDAP (Lightweight Directory Access Protocol) is an application protocol to access and maintain directory services. In LDAP, a BIND operation, when creating a session, etablishes an authenticated session [1]. In Java, LDAP oparations are done through the JNDI (Java Naming and Directory Interface) API [2]. More specifically, the BIND operation is done by creating an InitialDirContext
with the required authentication information.
// the protocol is either ldap or ldaps String ldapUrl = "ldap://directory.service.provider:389"; Hashtableenv = new Hashtable (); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, ldapUrl); // username/password authentication env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_PRINCIPAL, username); env.put(Context.SECURITY_CREDENTIALS, password); // bind with the above authentication info DirContext context = new InitialDirContext(env);
Context.SECURITY_AUTHENTICATION specifies the mechanism of authentication.
Anonymous | The default mechanism is "none" |
Simple | This mechanism consists of authenticating using the user name (usually fully qualified DN) and the password in clear-text. This is not a secure mechanism because the password is transmitted in clear-text. Set the value to "simple" |
SASL | Only in LDAPv3, this pluggable mechanism uses SASL (Simple Authentication and Security Layer). Currently defined SASL mechanisms are: Anonymous, CRAM-MD5, Digest-MD5, External, Kerberos V4, Kerberos V5, SecurID, S/Key [3].
To use a particular SASL mechanism, specify its (Internet Assigned Numbers Authority) IANA-registered name as value. An ordered list of space-separated mechanism names, such as "DIGEST-MD5 SECURID" , may also be used; the LDAP server will use the first mechanism it supports. |
DNS SRV record
The authentication above requires the knowledge of the host and the port of the LDAP server. But how can a LDAP client locate such provider in the first place? This is where DNS (Domain Name System) comes into play, more specifically the DNS RR (Resource Record) called Service record. A SRV record specifies the location of the server(s) for a specfic protocol and domain [4]. If a LDAP client wants to discover a LDAP server that supports TCP protocol and provides directory service for the domain example.com, for instance, it does a lookup of _ldap._tcp.example.com
.
Microsoft defines SRV record for its domain controller that can be used to locate the AD(s) for a given domain. The SRV record to look up for is _ldap._tcp.dc._msdcs.example.com
. Below is an example of lookup of AD servers for the domain lab.nwsummit.com using the (Linux) nslookup command:
% nslookup > set type=srv > _ldap._tcp.dc._msdcs.lab.nwsummit.com Server: 127.0.1.1 Address: 127.0.1.1#53 Non-authoritative answer: _ldap._tcp.dc._msdcs.lab.nwsummit.com service = 0 100 389 labdc01.lab.nwsummit.com. _ldap._tcp.dc._msdcs.lab.nwsummit.com service = 0 100 389 labdc03.lab.nwsummit.com. _ldap._tcp.dc._msdcs.lab.nwsummit.com service = 0 100 389 labdc02.lab.nwsummit.com. Authoritative answers can be found from: labdc01.lab.nwsummit.com internet address = 10.0.0.11 labdc03.lab.nwsummit.com internet address = 192.168.0.2 labdc02.lab.nwsummit.com internet address = 10.0.0.12
The information returned for each SRV record contains - in order - the priority, the weight, the port, and the hostname.
DNS SRV lookup in Java
Now, how do we make a DNS SRV lookup in Java? The answer is JNDI. DNS is a naming service and JNDI is an API that abstracts the specific implementation of naming and directory services. The below sample code retrieves the SRV atributes of the "_ldap._tcp.dc._msdcs.lab.nwsummit.com" object from DNS. (Note that I've changed vocalulary to use Java centric terms instead of DNS centric, but they all refer to the same thing).
// lookup DNS SRV records DirContext context = new InitialDirContext(); Attributes attributes = context.getAttributes( "dns:/_ldap._tcp.dc._msdcs.lab.nwsummit.com", new String[] { "SRV" }); // display the records Enumeration extends Attribute> attrs = attributes.getAll(); while (attrs.hasMoreElements()) { Attribute attr = attrs.nextElement(); System.out.println( "--- Attribute ID: " + attr.getID() ); Enumeration values = attr.getAll(); while (values.hasMoreElements()) { Object value = values.nextElement(); System.out.println(value.getClass().getName() + " == " + value); } }
The above code produces the below output:
--- Attribute ID: SRV java.lang.String == 0 100 389 labdc03.lab.nwsummit.com. java.lang.String == 0 100 389 labdc02.lab.nwsummit.com. java.lang.String == 0 100 389 labdc01.lab.nwsummit.com.
As expected, there's only one attribute returned, which is the specified SRV attribute. Each value of the attribute is a String representation of the service record in the same format as specified in the DNS RR, namely priority, weight, port and hostname. Now it's just a matter of parsing the string to get the port and host of the AD server to connect to for authentication.
References
- [1] LDAP
- Basic information on the Lightweight Directory Access Protocol from Wikipedia
- [2] JNDI
- Java Naming and Directory Interface
- [3] Advanced Topics for LDAP Users
- Part of the Java Tutorials series with emphasis on LDAP via JNDI
- [4] DNS SRV
- RFC-2782 A DNS RR for specifying the location of services (DNS SRV)
- [5] Domain controller DNS SRV
- Microsoft's KB for locating domain controllers for Active Directory
Copyright © 2013, Northwest Summit. All rights reserved.