In a recent project there was a need to work with active directory users as well as external users that would register to an application. Each type of user would have different permission levels into the app’s data. The security expert told me that I wasn’t allowed to make direct calls to AD from the app which is sitting on the DMZ, that requirement killed the easy approach to just make a direct call to AD and authenticate.
After some searching I found ADAM which stands for Active Directory Application Mode. If you read all ADAM’s documentation, you will find out that ADAM allows maintaining a set of local ADAM users and by using methods such as Windows pass through authentication or AD proxy users you can authenticate AD users via ADAM, basically making ADAM the complete authentication service for an application. The security requirements asked for ADAM to be on the DMZ and to have ADAM making secure simple LDAP calls to the internal AD servers. I thought I could accomplish that by having ADAM deployed on a machine sitting on a specialized DMZ without joining it to the domain, but we were proved wrong. We talked to Microsoft for hours (or days!) on the phone and over newsgroups until one of the guys that helped us at Microsoft finally talked to the correct people and found out that there is no way ADAM could authenticate AD users without having it’s host Windows server being part of the domain. That took us a lot of time to figure out, now I had to convince the security guy that the only solution to the requirement was to have ADAM’s server joined to the domain. We were able to configure ADAM so that on one side it receives the app server’s requests via simple LDAP calls and on the other side it makes the thick secure domain AD queries to authenticate all internal users. Also, we setup ADAM to work using SSL and now we had a secure communication channel from the app server to ADAM and the regular secure AD calls from ADAM to the domain controllers. The security guy wasn’t all happy about the solution but we thought it was the best we could do with ADAM. The next problem to tackle has a name: userProxy.
The method we chose to maintain an AD pointer for internal users was the user proxy method. This method uses a synchronization setting file that synchronizes any number of AD users with ADAM. The problem with the synchronized users in ADAM is that the users’ class when in ADAM is userProxy, this type of user class is not supported by the default ASP .NET MembershipProvider and in order to find out I had lots of communication with Microsoft again and with other AD experts over forums. Then I saw this article that confirmed the theory that the userProxy is not supported by the provider. The only solution left to do was to create our own custom MembershipProvider which I did and by the way I made it a bit more flexible in terms of the LDAP queries it can handle. Now I had an app that was able to make secure LDAP queries using the provider pattern and ADAM as a middle tier to securely connect to AD, all of the ADAM users were supported naturally by ADAM with no special change in the provider code, this was cool and it was putting the app in a better shape to support both types of users. The only problem is that so far we could only authenticate, we needed to maintain different levels of authorization depending on the type of user, so here we go again, the next problem was authorization and specifically the problem had a name: AzMan.
AzMan is a product that helps maintain roles, tasks and operations for any application that might need them, basically manages the authorization part. AzMan can store roles on an XML file or can get hooked to an AD product like ADAM. Naturally you would think that since you have authentication in place using ADAM, AzMan should just use ADAM as it’s store, well we were proven wrong again. After more hours (days?) of endless calls to Microsoft we hit the right guys and they finally pointed out that AzMan requires all servers accessing it to be part of the domain which completely breaks our current implementation of having the app server detached from the domain and only the server hosting ADAM being part of the domain, authorization with AzMan had to be discarded. The quick solution to that was easy, use the database server that was serving the app’s data to maintain the Database Role provider data as well, we used the Oracle Role Provider for .NET between the DBA and myself we were able to set it up in hours, that solved all problems and the security code of the app didn’t need to be changed thanks to the provider model. A good thing is that no Role provider code was needed since Oracle provides the implementation for free.
The lessons learned with this experience are:
- In order to support internal AD users ADAM must be part of the domain or a more complex solution must be implemented such as ADFS.
- App servers can use ADAM and being detached from the domain if they are facing the internet.
- Always setup ADAM to use SSL in order to maintain a secure data flow.
- AzMan = Domain, you are in a much better place by just using the regular Roles DB providers.
If you ever need more details on the implementation I made for this project do not hesitate to comment on this blog.
No comments:
Post a Comment