Feb 11

Written by: admin
2/11/2009 11:05 PM

Quick Backgrounders...
For folks who are new to the topic of Active Directory (AD), here's a quick link:  http://en.wikipedia.org/wiki/Active_Directory
Microsoft has a great page here: http://www.microsoft.com/windowsserver2008/en/us/active-directory.aspx

Setting the stage...
For the most part, this is a blog entry about some recent thinking regarding user and user access.  For most, this may not be an exciting topic; but, what's interesting is thinking beyond what most developers code to...the global catalog or GC.

Let me preface by saying that this article is not about the interworking of AD, but more addresses the pitfalls and how to avoid them up front before development starts.

Like many developers, I stared with accessing the Active Directory with a simple need to authenticate user.  My first experience with AD was actually a small console application used to grab user e-mail addresses, groups/roles, from the global address list (GAL) via LDAP and Microsoft Exchange e-mail server.  Once I made that first connection and got data, things became pretty exciting.

At the time, not much information was available except some LDAP references that I found on the Internet.  I found that pointing to a single IP address or a domain server was a pain and not very scalable.  Well, until I found about the rootDSE (via ldap://rootDSE/) and the Global Catalog (gc://) .  I thought  "Wow! That's what I'm looking for!  Let's get busy writing some code!"

 

The aforementioned approaches worked for many years and today are very common practice;. However, until recently, I discovered using DotNetNuke's AD Provider that the "common practice" takes many local domain luxuries and may not suit real-world AD user Authentication or Authorization.  The experience taught me to think differently about AD and the overall scheme of user access. 

Let me also set the stage to say that the folks who created the AD provider did a nice job.  I personally would have coded a couple of things differently; but that (again) is not what this article is about.  The AD Provider does performs adequately for most needs.

Let's get started with a Real-World Example
Now for the meat of the topic.

I recently worked on a project to work with Microsoft Dynamics CRM (www.microsoft.com/dynamics/crm) which involved client contacts and related methods for web based provisioning services.  Microsoft Dynamics (CRM) was what is called a Source of Record (or SOR) for all client contact information.  MS CRM is a class-act product in my mind.

Without getting into too many details, our goal was to link a new database to CRM to assign services to companies, or better yet, allow access to companies to corporate online services and offerings.  To put it simply, companies (called accounts in CRM)  pay for subscriptions to use the service.  Their primary contacts (called Contacts in CRM) are the users we wanted to authenticate and authorize with Active Directory Groups.

Mapping an account as AD Organizational Units (OU) and contacts to those OUs seemed like a quick win for the team.  We knew that AD would provide a proven approach for logins; all our applications needed to do is talk to AD and we're done, right?  Well not so fast - the rules from Microsoft have changed a bit.

Caution ahead, things aren't how they seem...
One requirement we had seemed straightforward...Use the e-mail address to login.  E-mail addresses are unique from CRM.  They are easy for the user to remember because they use it for their job.  How hard could this be?  For the experienced AD person, there is a problem.  AD "sort of" supports e-mail addresses.

For instance, we'll use:  JohnDoe@JohnDoeCo.com.  John Doe can login to his network using: somedomain\JohnDoe or (in the new world of Microsoft)  JohnDoe@JohnDoeCo.com.  I don't know the real reason why Microsoft made the change from somedomain\John to using the e-mail address; but I'd go so far to say that it was because users kept forgetting to use the domain\usename format and email address just made more since.

Now with Windows 2008 (and I believe this is true about 2003) is that using e-mail address is a preferred method.  The login screen strips out the domain name and does its magic to login.   But, wait a second.... there are two places to store the login account information in AD.  (The userPrincipalName and the saAMAccount fields.)  I only bring up those places up to point out that the sAMAccount name is the pre-Windows 2000 name and that userPrincialName is the target of our discussion.

Ok, up to this point, let's assume John Doe is happy logging in daily to his company's network.  Also, Mr. Doe uses his e-mail to get his daily stock reports, e-mail from external (ehem) sources, etc.  So how would you make sure his experience is the same for your company?  If you plan to use AD It's not as easy as you might originally think.

Can Mr. Doe exist on your Active Directory domain?
Sure he can, but what would he login as?  See, that's the rub and why this article was written. :-)  Here are some issues we ran across and how he'd login:

mycompany\JohnDoe
JohnDoe@mycompany.com
Well, those won't work will they?  Our design requirement is to login as JohnDoe@JohnDoeCo.com.  Now, could code our application to do a lookup inside a database to lookup account info to authenticate against AD, but that really defeats the purpose of using AD in the first place, right?

The issues we'll encounter with AD is using the e-mail address.  The userPricipalName of the account will reject characters like the @ sign and for good reason.  We could strip out the @JohnDoeCo.com from the name, but what about another man JohnDoe@abcCo.com?  To distinguished them, each would have to login as:

JohnDoe@JohnDoe.com@mydomain.com
JohnDoe@abcCo.com@mydomain.com

The above examples may seem odd, but in reality, the format is key to our goal!  But Windows won't let us us that format, so if we change the rules a bit, both Mr. Doe(s) can login using their email address on your domain.  We'll come back to these logins in a minute.

External vs Internal AD Server
Assume for a minute you have a web site that your fellow employees login to.  Each of those emploees login with the help of Active Directory, your internal network may be mydomain.local or mydomain.com.  I don't claim to be an AD security expert, but I think I can safely say that no AD admin would comfortably put a corporate AD server online.  That opens the next topic of Security.

Create an External AD server to add an extra level of security
External to what?  Right?  There's no way that our admins would expose AD to Internet traffic.  Thus to say, that nearly most security folks wouldn't want the web server to exist in the same domain as the external AD server. 

So the design was to have a AD server in a secure area off the web server, but not a part of our corporate AD.  No trust anywhere.  We just needed a web server to connect to our new AD server.  Note: (and this is key) the web server was not to be a member of the domain forest -- which spells doom to classic AD connections, which kills access to GC:// and LDAP//rootDSEMost AD developers rely on the GC and rootDSE to connect.

An opportunity to have a nice and clean AD server appealed to the team and made our security folks happy.  However, our development team worked internally.  If a developer testing an application that connects using GC:// or ldap://rootDSE will never be able to connect because the external AD server must be referenced by IP address only.

THE SOLUTION  - Use IP or Fully qualified Name based AD addresses to connect to external server...
Ok, this is getting too long!  But there is much more to cover!  Here's the solution:
  • Avoid any AD code or provider that only supports gc:// or ldap://rootDSE access.  You can tell immediately if the provider asks for the root domain in the format of:    dc=mydomain, dc=com.  Chances are that they connect as: ldap://rootDSE/dc=mydomain,dc=com which will simply not work because that is an internal domain address.
  • Create an web server without AD installed, there's no need.
  • The external AD can live anywhere.
  • Code the application to use IP addresses or fully qualified names:  ldap://10.1.2.3/dc=mydomain,dc=com
  • When accepting user names in the application (these next couple of bullets are just as important),make sure to properly format the user name coming in.  There are certain rules:
    • No special characters in the user name (always use the userPrincipal name, not the pre-2000 fields)
    • "Squat" the @ sign and make any periods (.) go away.  As you'll find, you don't really care what the username becomes as long as it works right?  Using our John Doe example, the email addresses become: JohnDoe_JohnDoeCocom and JohnDoe_abcCocom.  (An odd note about Windows 2008, it won't allow login with a .com in the name... i haven't tried .net, .org, or anything else.  I just decided remove periods all together.
    • Remember, your users are logging into application, not your external domain. 
    • The security benefit is that even if someone reached your external AD server, they will not be able to login unless they know your special replace rules for the @ sign or the periods, or any other invalid character. :-)
  • Be careful with the @ sign and . replacement rules -- If you don't care to think of all the rules, you could always use a hashed (encrypted) version of their email address.  The hashed method might be best if you have concerns of email address security of your clients.
  • HAVE FUN!
Closing...
I hope you enjoyed this post. However, just getting user sign-on must be thought out to the point of security concerns, development practices, third-party AD Providers, etc.   In weeks to come, I'll have some follow ups to this blog as not all the issues have been ironed out.
 

Tags:

Your name:
Title:
Comment:
Security Code
Enter the code shown above in the box below
Add Comment    Cancel