Is there a way in Java to query Active Directory for a users attributes given an existing javax.security.auth.kerberos.KerberosTicket that was forwarded to my code? I know I want to use Ldap to do the search but I am confused on how to use this KerberosTicket object to Bind to ldap. Currently I am using Spring-Ldap and Spring-Security to communicate with Active Directory and using simple authenticate credentials I can Bind a username and password to authenticate my user and retrieve all my attributes, roles, etc. However in the case when I am passed a KerberosTicket from that Active Directory server I do now know how to Bind myself because I don't know the password for this user. I am currently not calling login() from a LoginContext to get my KerberosTicket its been forwarded to my code as an encrypted java object.
Java – Use an existing KerberosTicket to Bind to Ldap and search for users attributes
javakerberosldap
Related Solutions
The docs for java.io.Serializable
are probably about as good an explanation as you'll get:
The serialization runtime associates with each serializable class a version number, called a
serialVersionUID
, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a differentserialVersionUID
than that of the corresponding sender's class, then deserialization will result in anInvalidClassException
. A serializable class can declare its ownserialVersionUID
explicitly by declaring a field namedserialVersionUID
that must be static, final, and of typelong
:
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
If a serializable class does not explicitly declare a
serialVersionUID
, then the serialization runtime will calculate a defaultserialVersionUID
value for that class based on various aspects of the class, as described in the Java(TM) Object Serialization Specification. However, it is strongly recommended that all serializable classes explicitly declareserialVersionUID
values, since the defaultserialVersionUID
computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpectedInvalidClassExceptions
during deserialization. Therefore, to guarantee a consistentserialVersionUID
value across different java compiler implementations, a serializable class must declare an explicitserialVersionUID
value. It is also strongly advised that explicitserialVersionUID
declarations use the private modifier where possible, since such declarations apply only to the immediately declaring class —serialVersionUID
fields are not useful as inherited members.
There are 3 authentication protocols that can be used to perform authentication between Java and Active Directory on Linux or any other platform (and these are not just specific to HTTP services):
Kerberos - Kerberos provides Single Sign-On (SSO) and delegation but web servers also need SPNEGO support to accept SSO through IE.
NTLM - NTLM supports SSO through IE (and other browsers if they are properly configured).
LDAP - An LDAP bind can be used to simply validate an account name and password.
There's also something called "ADFS" which provides SSO for websites using SAML that calls into the Windows SSP so in practice it's basically a roundabout way of using one of the other above protocols.
Each protocol has it's advantages but as a rule of thumb, for maximum compatibility you should generally try to "do as Windows does". So what does Windows do?
First, authentication between two Windows machines favors Kerberos because servers do not need to communicate with the DC and clients can cache Kerberos tickets which reduces load on the DCs (and because Kerberos supports delegation).
But if the authenticating parties do not both have domain accounts or if the client cannot communicate with the DC, NTLM is required. So Kerberos and NTLM are not mutually exclusive and NTLM is not obsoleted by Kerberos. In fact in some ways NTLM is better than Kerberos. Note that when mentioning Kerberos and NTLM in the same breath I have to also mention SPENGO and Integrated Windows Authentication (IWA). IWA is a simple term that basically means Kerberos or NTLM or SPNEGO to negotiate Kerberos or NTLM.
Using an LDAP bind as a way to validate credentials is not efficient and requires SSL. But until recently implementing Kerberos and NTLM have been difficult so using LDAP as a make-shift authentication service has persisted. But at this point it should generally be avoided. LDAP is a directory of information and not an authentication service. Use it for it's intended purpose.
So how do you implement Kerberos or NTLM in Java and in the context of web applications in particular?
There are a number of big companies like Quest Software and Centrify that have solutions that specifically mention Java. I can't really comment on these as they are company-wide "identity management solutions" so, from looking the marketing spin on their website, it's hard to tell exactly what protocols are being used and how. You would need to contact them for the details.
Implementing Kerberos in Java is not terribly hard as the standard Java libraries support Kerberos through the org.ietf.gssapi classes. However, until recently there's been a major hurdle - IE doesn't send raw Kerberos tokens, it sends SPNEGO tokens. But with Java 6, SPNEGO has been implemented. In theory you should be able to write some GSSAPI code that can authenticate IE clients. But I haven't tried it. The Sun implementation of Kerberos has been a comedy of errors over the years so based on Sun's track record in this area I wouldn't make any promises about their SPENGO implementation until you have that bird in hand.
For NTLM, there is a Free OSS project called JCIFS that has an NTLM HTTP authentication Servlet Filter. However it uses a man-in-the-middle method to validate the credentials with an SMB server that does not work with NTLMv2 (which is slowly becoming a required domain security policy). For that reason and others, the HTTP Filter part of JCIFS is scheduled to be removed. Note that there are number of spin-offs that use JCIFS to implement the same technique. So if you see other projects that claim to support NTLM SSO, check the fine print.
The only correct way to validate NTLM credentials with Active Directory is using the NetrLogonSamLogon DCERPC call over NETLOGON with Secure Channel. Does such a thing exist in Java? Yes. Here it is:
http://www.ioplex.com/jespa.html
Jespa is a 100% Java NTLM implementation that supports NTLMv2, NTLMv1, full integrity and confidentiality options and the aforementioned NETLOGON credential validation. And it includes an HTTP SSO Filter, a JAAS LoginModule, HTTP client, SASL client and server (with JNDI binding), generic "security provider" for creating custom NTLM services and more.
Mike
Best Answer
In your LDAP connection environment, set Context.SECURITY_AUTHENTICATION to "GSSAPI". Then create the InitialLdapContext inside a privileged action:
InitialLdapContext context; Subject.doAs(subject, new PrivilegedAction() { public Object run() { context = new InitialLdapContext(env, null); } };
You get the subject variable by calling getSubject() on your LoginContext. env is the environment. You will have to catch a NamingException somehow. Notice that to make this work on newer Windows versions, you have to set a Registry entry, see http://java.sun.com/j2se/1.5.0/docs/guide/security/jgss/tutorials/Troubleshooting.html (search for registry).