Showing posts with label authentication. Show all posts
Showing posts with label authentication. Show all posts

Friday, May 23, 2008

AD Authentication and Java

Well, it was only a matter of time before my job would require our Java apps to authenticate against Active Directory. For those who don't know what Active Directory (AD) is (myself included up till last year), AD is a Microsoft Windows implementation of LDAP. It is typically used in Windows 2000 based networks to tie together the standard IT resources like mail, calendars, and desktop computers. Those of us who are on a network that uses AD typically have a desktop that authenticates against AD, as well as MS Outlook for email. The good thing about a central authentication source for network credentials is that is allows for a single username and password to be used for things. Which can eventually lead to "Single Sign-On" (which will be discussed later, when I learn how to do it).

Anyway, a central source for authentication credentials also helps with web applications on that network, because now we no longer need to worry about password management, or user registration. That can reduce the project schedule by a week or two, depending on how strict your organization's password and user registration requirements are.

So, how do we do it? Well, it is actually pretty simple. Like I said, AD is basically another version of LDAP, so in Java you can use the Java Naming and Directory Interface (JNDI). There are a bunch of LDAP classes in the javax.naming.ldap package that can help. And because the Java API is so robust, it gives you a ton of flexibility to customize your code as much as possible. At the same time, it can seem a bit intimidating. Sun has some pretty good information on their website about LDAP authentication, which can also be used for AD Authentication. Lets take a look at some code.
Hashtable env = null;
DirContext ctx = null;
boolean isAuthenticated = false;

try {
try {
String loginId = "yourdomain\\avgwebgeek";
env = new Hashtable();   // hash table for your LDAP properties

// set up the LDAP properties
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://myadserver.mydomain.com:389");

// Set the authentication mechanism to be simple
env.put(Context.SECURITY_AUTHENTICATION, "simple");

// login credentials
env.put(Context.SECURITY_PRINCIPAL, loginId);
env.put(Context.SECURITY_CREDENTIALS, password);

// the following is helpful in debugging errors from the
// AD server side of things
//env.put("com.sun.jndi.ldap.trace.ber", System.err);

// Create the initial directory context
ctx = new InitialDirContext(env);
isAuthenticated = true;
} catch (AuthenticationException e) {
// this exception is typically found with incorrect credentials
e.printStackTrace();
} catch (NamingException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
} finally {  
try {
ctx.close();
}catch (NamingException e) {
e.printStackTrace();
}
}

if (isAuthenticated) {
System.out.println("I am authenticated.");
} else {
System.out.println("I am not authenticated.");
}

This is a very simple application. It does the job, however, it is not very secure. The problem is that I am setting the Context.SECURITY_AUTHENTICATION to "simple". What this means is that your password is being sent over the network through clear text. If someone is running a network sniffer, they can read your password from your IP packets. One way around this is to make sure that your LDAP connection is handled over SSL. In other words, use "ldaps://" with port 636, and not "ldap://" on port 389.

If your server is not setup to handle SSL, or you just want a little extra security, you can change the Context.SECURITY_AUTHENTICATION to "DIGEST-MD5". However, as I found out, AD treats this a little differently. The concept of using "yourdomain\\yourusername" needs to be reduced to just "yourusername". It has something to do with how AD 2003 sets up the HASH for the MD5. This method will use a Hashing algorithm to be verified with the server, that you indeed know your password.

So, that's it for AD authentication. Like I said, the Java API can let you do a lot more. You can set up controls to do searches, find specific user information, and find groups assigned to users. AD groups can be used to help with the Authorization portion of your apps. Take a look at the javax.naming.ldap API, there is a lot there, but it isn't too hard to follow.

Monday, April 28, 2008

PHP and LDAP

The joys of authentication. So, now I am working on running some of our PHP apps to authenticate against Active Directory (AD). Well, my limited knowledge in AD is telling me that it shouldn't be too hard. After all, AD is just a Microsoft interface to LDAP. Right?

Well, it turns out that, yeah, from a PHP perspective, it is. It is actually pretty easy, once you are comfortable with working with an LDAP structure.

So, here is the basics of it. I have a simple page that all it does is print out the results of a simple authentication to an AD server:
<html>
<body> 
<h1>AD Test</h1>
<?php
// Variables to use with ldap_bind
$ldapuser  = 'username@some.domain.com';     // ldap username with suffix
$ldappasswd = 'notmyrealpw';  // associated password

// connect to AD server
$adconn = ldap_connect("ad_controler.myco.com")
or die("Could not connect to LDAP server.");

// if a connection was made attempt a binding
if ($adconn) {

// bind to ldap
$ldapbind = ldap_bind($ldapconn, $ldapuser , $ldappass);  

// Check authentication
if ($ldapbind) {
echo "User is authenticated.";
} else {
echo "User was not authenticated.";
}

// unbind the connection
ldap_unbind($adconn);
}
?>
</body>
</html>


Basically, you have your username, for example avgwebgeek. Then you have a suffix, which is your account suffix for your domain, for example "@myco.com". Put them together (along with a password) and you have your AD authentication information. Of course, the username and password would be sent through request parameters. Granted, this is a pretty simplistic view of AD authentication. You can do a whole lot more, like searching, and updating AD information. I learned all about it by looking through the adLDAP Project. The hard part was realizing that I didn't have PHP enabled on my server. Hint: if you get a message like "Call to undefined function: ldap_connect() ", that means that your LDAP isn't enabled for PHP. The adLDAP page has a FAQ that explains that as well.

Friday, January 05, 2007

Dead Winter Dead and Web Application Security

Wow, I haven't added to this blog in over a month. The ironic thing is that the winter time is usually the slowest time for a developer who works for the government. Especially where I work. The organization that I work for are re-organizing themselves, and have no time to look at proposals or statements of work. So, we just sit and wait for something exciting to happen. Since we are on a fixed price contract, we still get paid.

Although, times haven't been that slow for me at work, and home. My wife, kids, and myself have all been sick. The relatives came in from out of state. And the holiday season in general makes simple tasks a mad house. But enough of this non-technical stuff. Anything interesting?

Well, yeah, kind of. I was assigned a task to look into new security requirements for many of our apps. These requirements were signed by President Bush about 2 years ago. Some are simple, like session timeouts must be set at 30 minutes, and tracking all access to "Personally Identifiable Data" (aka Social Security Numbers). Some were a little more complex, like enforcing 2-factor authentication. Since many of our apps deal with secure data, and because of the whole VA Laptop thing that happened last summer. My group needed to do something, fast. For all new apps, the security requirements have already been put in place, but the older apps needed to be updated.

The interesting part was working on a solution for enforcing 2-factor authentication. Typically, a website has 1-factor authentication, a password to proove that the user is valid. 2-factor authentication is a way of not only proving the user is valid with something that they know, but to request something that they have as well. Things like smart cards, biometrics, and security tokens are just a couple ways to help prove that you are who you say you are. Our government client decided on using security tokens to solve this problem, in the short term, at least.

The security token works on the concept of this little device that displays a 6 digit number, that changed every minute. A user would enter a pin and the 6 digit pass code to prove their identity. However, these little devices are about $70 a pop. Considering that hundreds to thousands of people use our systems, that can get costly. Well, it turns out that most people who use the systems, don't need to have access to the secure data anyway, they only need access to the non-secure data on the sites. We have user roles to enforce who can see what. However, there can be 2 people on the same role who can see the same data, but only one needs to see the secure data. We wanted a simple way of hiding the secure data, without recreating the users into new roles, and causing as little modification to the code as possible. Therefore, only a small fraction of people will need the tokens.

All of our security and user authentication code was generated through ColdFusion/Java and an Oracle back end. The use of the ISAPI dll that came with the secure tokens wasn't useful for us, and I couldn't find anything on the net about this type of implementation. So I had to design our own way of doing this. I will discuss my solution in my next post. If anyone has run though this situation before, I would love to hear how you handled it.