ASP.NET 2.0 - Playing with ActiveDirectory (check whether user exists, etc)

It had been a wonderful day of my programming life. I was given an assignment to look into active directory, and test out the web development authentication with it. It was really a challenging one. Just imagine I have zero active directory experiences but I am still able to cope in 2 days.

 

This is my scenario:

 

*I configured my 1st active directory and domain controller + DNS. Cool :P Now I understand a lot on OU, CN, LDAP by configuring. Never like infra stuff in the past, but I enjoyed this time.

 

You have an active directory in a domain controller (under this domain community.com). You have a web server which is connected to this domain. The member’s profile of the system is stored in the database. There is a column in the member’s table that consists of the active directory account. So it means that certain user has access to the active directory and some cannot. The column must be null by default. The reason why there is a profile in the database as we are working on a huge system. Within the huge system, there is already existing application utilizing the database for member’s profile. There are around 10,000 members within this private system and I don’t think it is a good idea to move to Active Directory, then ask each of the members to change password. There are more design considerations on this.

 

User A: PC connected to the domain

A user runs this web application; he will be auto authenticated and able to access certain resources on the site

 

User B: PC not connected to the domain

A user runs this web application. He will be prompted to enter username, domain and password to authenticate. If fail, will get a 401.1 error.

 

Looks simple right.

 

So at first, when I heard it was related to ActiveDirectory I tried to look into System.DirectoryServices and ActiveDirectoryMembershipProvider. Trust me that it might looks very easy from the outside, but it was not a simple task to work on the API. You need to understand ActiveDirectory and LDAP first before taking this adventure ride. It was really a pain to me working on this.

 

I tried a number of ways:

 

a) To force to use System.DirectoryServices, in the directory security I assign the process to be a domain user or admin account. By doing this, all your web application has the access to this specific account, which sounds kind of stupid. Coz I will have so many members and each of them must be authenticated by itself.

 

Mission Failed.

 

b) I try to look into ActiveDirectoryMembershipProvider. Looks cool. You have to store a specific user account inside the web.config itself which did not make any sense to me. Just like point a. Try not to place a domain admin account inside here. You need to specify the account name and password.

 

Mission Failed.

 

c) How about doing some impersonation? Then get the logon user name by “Environment.UserName” or “System.Web.HttpContext.Current.User.Identity.Name”. Then pass this windows logon id for DirectoryEntry + DirectorySearch query. Sigh … it does not work. But if you do it manually, you will work. Kind of tough to explain on this one. You must set impersonation here or else you will not get accurate information. Furthermore, maybe I did a badly job on my DirectorySearch query. Oops L

 

d) Then I thought it could be authorization issues. But thinking twice, it should not be.

 

Life moves on and on… still not able to solve it. Suddenly something hit my mind :D

 

Anyway you will be surprised that I do not use any codes that involve System.DirectoryServices or ActiveDirectoryMembershipProvider on this one. I did not use the LogonUser API as well. So how did I solve this problem?

 

The answer is there is a solution for everything. When someone is being assigned a task, try to think if there is a simpler way of doing thing. Learn a lot this time.

 

With this implementation, I do not need to configure anything in the IIS, which is the best part. So anonymous user will be prompted to login. Hehe :D

 

        if (!Page.IsPostBack)

        {

            string test = System.Web.HttpContext.Current.Request.ServerVariables["LOGON_USER"].ToString();

 

            if (System.Web.HttpContext.Current.Request.ServerVariables["LOGON_USER"] == "")

            {

                System.Web.HttpContext.Current.Response.StatusCode = 401;

                System.Web.HttpContext.Current.Response.End();

            }

            else

            {

                // Request.ServerVariables["LOGON_USER"] has a valid domain user now!

 

                string changeDomainName = (Environment.UserDomainName).Substring(0, Environment.UserDomainName.Length - 1) + ".com";

                string account = Environment.UserName + "@" + changeDomainName;

                enObj.sADAccount = account;

 

               

 

                Response.Write(brObj.GetFullName(enObj));

            }

        }

 

 The rule is simple here. If you are authenticated, you will query the database and get the full name of the member’s profile. If not, you will be prompted login screen (max 3 times). If failed, then you will get “you are not authorized error”. If you manage to login, you still can get the full name. Sound easy right J

 

Anyway the term to find here is single sign on. I never thought of that till 5 minutes ago – 10.55 p.m.

Published Thursday, November 16, 2006 11:25 PM by chuawenching

Comments

# re: ASP.NET 2.0 - Playing with ActiveDirectory (check whether user exists, etc)

Friday, November 17, 2006 9:24 AM by Softwaremaker

> With this implementation, I do not need to configure anything in the IIS, which is the best part

This is the strangest statement I have heard and you are the first (and hopefully only one) I have heard this from.

I really cannot fanthom why you are writing codes (which lengthens the dev>build>test>debug>test>deploy>manage cycle) when IIS can integrate with AD already ?

Have you ever taken extensibility and flexibility into account ?

I would like to see you manage a web farm of 400 where your codes are all deployed and you have to deploy new your code base. How would you manage that ?

You really should get out of the 1-man local machine single code-base mindset.

My advice: Focus on business functionality and leave the tools to do the rest.

# re: ASP.NET 2.0 - Playing with ActiveDirectory (check whether user exists, etc)

Friday, November 17, 2006 11:16 AM by chuawenching

Can you tell me more on this "IIS can integrate with AD already"?

Thanks.

# re: ASP.NET 2.0 - Playing with ActiveDirectory (check whether user exists, etc)

Friday, November 17, 2006 3:26 PM by Softwaremaker

http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/523ae943-5e6a-4200-9103-9808baa00157.mspx?mfr=true

Wouldnt it be strange that Microsoft doesnt provide anything that integrates the host of 99% of its .NET web applications to integrate with one of the most used directories in the world ?

You only use ADSI for more complex scenarios just as allowing a Web Application to communicate with AD directly.