If you work on .NET 3.5 or newer, you can use the System.DirectoryServices.AccountManagement
namespace and easily verify your credentials:
// create a "principal context" - e.g. your domain (could be machine, too)
using(PrincipalContext pc = new PrincipalContext(ContextType.Domain, "YOURDOMAIN"))
{
// validate the credentials
bool isValid = pc.ValidateCredentials("myuser", "mypassword");
}
It's simple, it's reliable, it's 100% C# managed code on your end - what more can you ask for? :-)
Read all about it here:
Update:
As outlined in this other SO question (and its answers), there is an issue with this call possibly returning True
for old passwords of a user. Just be aware of this behavior and don't be too surprised if this happens :-) (thanks to @MikeGledhill for pointing this out!)
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
You do an NTLM/Kerberos/Negotiate SSPI exchange loop. There is a a full sample on MSDN for both the client and the server. To be clear: you do not use any sort of LDAP access explictily. Is the LSA (Local Security Authority) that talks with LDAP and establishes the identity of the client. If you are succesful in doing the entire SSPI loop, the authentication has succeeded already and the client identity is alread authenticated against the LDAP. If your server needs to know the client identity (eg. to know the use rname) it retrieves it from the security context resulted in the SSPI loop using the
QueryContextAttributes(..., SECPKG_ATTR_NAMES,...)
and retrieves the user name from theSecPkgContext_Names
structure.