Integrating LDAP Active Directory into your ASP.Net Web Portal
(C# or VB.NET)
Contents
Introduction. 2
Authentication. 2
Windows Pass through authentication. 2
Form Authentication. 3
User Registration / Account Creation. 3
Password Management. 4
Forgot Password. 4
Change Password. 5
User Profile Management. 6
Advanced Profile Management. 6
Option 1 – Use Active Directory. 6
Option 2 – User SQL Table. 7
Account Cancellations. 7
Permissions. 8
Groups. 9
Creating Groups. 9
Add User to a group. 9
Deleting Users from a Group. 10
Deleting a Group. 10
Listing Members of a Group. 10
Listing all “effective”
members of a Group. 10
Auditing Permissions. 11
This article will guide you through the best practices and
method of using LDAP Active Directory as your user store for credentials and
account information in your ASP.NET web applications or portal that you will develop in
C# or VB.Net.
A traditional approach creating user store is storing
the users in a database and managing them there. But what if your have a
company portal and you already use Active Directory? Or what if you want to
make it easy on yourself and leverage some of the Active Directory or ADAM
features such as account expirations, password policies, connectivity to
Exchange, etc? what if you already have a set of users that you are hosting in
Active Directory and now you want to build a website or portal for those users
without managing two sets of accounts? This is when this article will be
helpful.
When developing a web portal that uses Active Directory users,
there are a few things that you need to consider in your web application?
-
How will your web application communicate with Active Directory?
-
How will you authenticate against Active Directory?
-
How do you allow users to self-register into the portal?
-
How will users be able to change their passwords or reset their
passwords?
-
How will the users be able to update their profile information such as
email?
-
How will the portal administrators be able to assign permissions for
users?
-
How will administrators be able to add users to certain Active Directory
groups without going into Active Directory Users and Groups?
A special application called the .Net Active Directory Wrapper (http://www.dotnetactivedirectory.com)
has been developed that helps address this specific need and this article will
show you how easy it is to interact with Active Directory using this module and
to do the various tasks. The .Net Active Directory Wrapper uses ADSI and
System.DirectoryServices Namespace to perform its functions.
When building your own custom app that leverages Active
Directory users, probably the first step you need to do is authenticate those
users that are logging in.
There are two ways you can authenticate a user.
1. Pass
through authentication – here you find out who the user is from their
windows session. Based on that logged in user, your application can decide
whether to give the user access or not. No need for the user to input any
username or password here.
2. Logging
in using a login form – here the user has to input the user name and
password explicitly into a form. Your application will grab that information
and authenticate based on the credentials inputted.
Here you find out who the user is from their windows
session. Based on that logged in user, your application can decide whether to
give the user access or not. No need for the user to input any username or
password here.
Usually this means the user is on the same domain as the
portal application’s web server.
To find out who the user is from the windows session, you
can use the following code:
LDAPManager.CurrentUser()
this will return a string with the user’s account in
the following format: domain\username
if you wish to get the ADObject of that User to pull, say
the email address of that user. Use the following line.
ADUser oUser = LDAPManager.GetCurrentUser();
string email = oUser.email;
In forms authentication, the user is manually
inputting their credentials (username and password) into a login form. Use the
authentication method if the user is not part of the same domain as the web
server.
The process of authenticating a user involves a few subtle
steps. You need to keep a few things in mind when doing this.
1. What
domain is the user logging into?
2. Are
the inputted credentials correct (meaning username and password)
3. Is
the account expired?
-
If incorrect logon, you may want return the user with the reason of
failure. Were they bad credentials or was the account expired?
In this .Net Active Directory Wrapper module, all steps
listed above are available in one function as follows.
LDAPManager.Login(username, password);
The response from the above function returns true if the
login is successful and false if not successful. If false, the response
indicates why the logon is not successful, either because the account it was a
bad username and password or it is an expired account.
Most portal applications allow users to register in order
access their portal or certain parts of the portal. For example, eBay requires
you to browse and search for products but in order to buy something you must
register first and create an account.
.Net Active Directory allows users to register easily.
The registration involves asking for 3 necessary components:
1. Username
2. Password
3. Email
The registration process may also require you to include
additional information about yourself such as address, phone number,
etc..
But the minimum core is username, password and email.
LDAPManager.CreateUser(username, password, email); OR
LDAPManager.CreateUser(username,password, email, location);
After creation of the user then you can update that
user’s properties such as the address and phone numbers as follows:
ADObject oUser = new ADUser();
oUser.StreetAddress = “streetaddress”;
oUser.Phone1 = “1112223333”;
oUser.CommitChanges();
Password Management addresses two password management
features
1. Forgot
Username and Password (password resets)
2. Changing
password
In most applications when a user forgets his/her password
they are prompted with a form where they fill in the email address or their
username and a link will be sent to that user’s email address that allows
them to reset their password and pick a new one.
This is provided that the email address is a unique
identifier for the user account in Active Directory. You may also choose for
them to input their usernames or sAmAccountName.
The email link that gets generated will have a unique id
(usually a GUID) encoded into the URL. When the user clicks on the link
in their email, the server checks to see if the GUID matches the GUID that it
issued to that user, therefore confirming that the user trying to change the password
is the same user that requested the password change. (Just a way of confirming
the user requesting the password in fact owns that email address).
This is easily doable with the .Net Active Directory Wrapper
as follows:
{LOGIC TO CHECK IF GUIDs MATCH}
{if match then}
ADUser oUser = New ADUser(“myemail@email.com”); //finds
the object from AD with that email
Try{
oUser.ChangePassword(“newpassword”);
}
{end if}
Changing password is also a classic functionality in any
fully baked application. The user in this case chooses to change his password
for any reason, maybe he had it shared with his girl friend and now they broke
up. Usually here the user is presented with a form that has three fields.
1. Old
Password field
2. New
Password
3. Confirm
New Password
The logic here should be as follows:
1. If
the old password is correct then
2. If
the new password field = the new password field then
3. If
the password meets minimum requirements, then
4. Change
password
Condition 1 and 2 above need to be handled by the application.
Condition 3 can be handled by Active Directory (or whatever LDAP system
you’re using).
Condition 1 and 2 are easily available in the .Net Active
Directory Wrapper module as follows:
ADUser oUser = New ADUser(“janderson”);
Try{
oUser.ChangePassword(“oldpassword”,”newpassword1”,”newpassword2”);
}
Catch{
{code: tell user password did not change successfully
because of e.message}
}
In your portal, you will probably need to add the functionality
for your users or subscribers to be able to go in and update their personal
information and profiles. Some of the common profile properties are:
-
Account Login
-
Email
-
Personal Street Address, City, Country, Zip
-
Business Street Address, City, Country, Zip
-
Primary Phone number
-
Secondary Phone number
-
Title
In .Net Active Directory Wrapper, you are able to easily
read and write that information to the user object as follows:
Try{
oUser.mail = “rjonhson”; //set the
user’s email
oUser.commit; // saves the changes to Active Directory
}
You may ask us ok, what if we need to store information
about that user that is Active Directory does not support such as
“Hobby” or “How did you hear about us?” Little do
people know that you can actually store as many “attributes” as you
wish in an Active Directory object usually by changing the user schema class.
But more simply this could be done in another way.
This is also done using .Net Active Directory Wrapper as
follows:
Try{
oUser.Properties[“Hobby”] =
“singing,fishing”; //where hobby is whatever new attribute
you want.
oUser.Commit;
}
Keep in mind that if you decide to add new attributes that Active
Directory does not use by default, you will need to document and plan the new
attributes prior to actually using them, much like you would plan a database
table.
The other option of storing additional information about a
user may also be storing that user information in a database table like SQL
Server.
You will need a way to map the account in Active Directory
to the table row that hosts the rest of the profile. There is probably no
better choice to use than the username or the “sAMAccountName”
A portal user may decide to cancel his account or
subscription. What you may wish to do with the users’ Active Directory
account may vary depending on what you are looking for. If a user opts to
cancel what will you do with their Active Directory account?
1. Delete
the Account from Active Directory
2. Lock
the Account
3. Or
Lock the Account, take some action, the delete the Account?
Active Directory Wrapper allows you to easily delete or lock
the account. This is done with the following lines of code.
Try{
LDAPManager.DeleteUser(“domain\user”);
}
OR
If you wish
Try{
LDAPManager.LockUserAccount(“domain\user”);
}
Your portal application will probably need to be permission
sensitive. You need your application to be able to restrict permissions
on its sites, objects, or artifacts depending on who the user is, and there is
no better way of leveraging Active Directory groups to do that.
Let’s say for instance that you have a site and you
only allow the users that belong to the “Administrators” group to
enter that site. How do you enforce that security on the page?
Another tricky part of this is what if group B is in the
Administrator group and user1 is in group B?
In that case you would want user1 to be able to see the
page.
The best way to do this to run the security check on the ON
LOAD event of that page. Let’s take a look:
On Load{
If (LDAPManager.IsInGroup(“domain\userid”,
“groupname”)) {
{CODE: Display the Administration Page}
}
Else{
{CODE: redirect to Access Denied Page}
}
}
Another function that will come in handy is the
IsCurrentUserInGroup. This function will use the current user that is logged
into the windows desktop session and see if they are in the group. You would
simply have to replace the function above with the following:
LDAPManager.IsCurrentUserInGroup(“groupname”);
Note that this function returns the effective group that the
user is in as we mentioned above. By “effective” we mean the
following.
If the user is a member of group A and group A is a member
of group B. then the user is “effectively” a member of group B.
The IsInGroup function returns true if
User.IsInGroup(“B”) is executed.
Portal Administrators need to be able to create Active
Directory groups without going into Active Directory. A web interface for
viewing, creating and deleting groups needs to be put in place.
Using .Net Active Directory Wrapper, this could be done
easily via the following methods.
To create a group simply pass the group name you wish to
create to the CreateGroup function as a string. The group will be a global
security group and the location of the group will default to the Users
container
LDAPManager.CreateGroup(“groupname”);
There is also the option of adding that group in a specific
OU.
LDAPManager.CreateGroup(“groupname”,”OUName”);
This function works provided that that there is only one OU
with that name. If more OUs exist you can use the path to where you wish to
create that group as follows:
LDAPManager.CreateGroup(“groupname”,
“LDAP://CN=User1,CN=users,DC=domain,DC=com”);
Adding a user to a group will often be necessary in Active
Directory and has many applications.
You may have few key groups in your Active Directory.
Here’s an example:
1. Portal
Administrators – user’s that manage permissions, accounts, content,
etc..
2. Viewers
– users that just see content
3. Power
Users – users that can add content and manager a subset of users.
Adding users to the various groups could be done easily in
.Net Active Directory Wrapper as follows:
LDAPManager.AddUserToGroup(“domain\user”,”groupname”)
//where groupname is the common name of the object
oUser.AddToGroup(“PowerUsers”);
Note that the function above will execute immediately and
there is no need to use the commitchanges function to add the use to the group.
The other method is to use the AddUsers from the ADGroup
object.
ADGroup oGroup(“PowerUsers”);
oGroup.AddUsers(“User1”);
if you wish to pass many users at once you can use:
oGroup.AddUsers(new string[] { "John", "Mike", "Sandeep" });
Obviously if you can add users to a group you must also be
able to remove users.
oGroup.RemoveUsers(“username”);
or to remove a group of users
oGroup.RemoveUsers(new string[] { "John", "Mike", "Sandeep" });
Deleting an Active Directory group without going into Active
Directory Users and Computers will probably be an important task for an
administrator to do. You can easily code this in your application as follows:
LDAPManager.DeleteGroup(“groupname”);
Or you can also use the method found in the ADGroup object.
ADGroup oGroup = new ADGroup(“mygroup”);
oGroup.Delete();
When administering your portal, you will probably want to
know who is in the “Powerusers” or any group per say.
In order to find out who thedirect members of a group are
use:
oGroup.Members();
This function will return an ArrayList of all the usernames
that are found in that group.
oGroup.Members will list the users that belong that group.
But consider this scenario:
you have group A that has user1, user2 and user3 and group B
it.
In group B you have user 3 and user 4.
“Effectively”, User 3 and User 4 are technically
also belong to group A because group B in A. and this scenario can get much
more complicated.
To find out all the effective members of a group use
oGroup.EffectiveMembers();
This will return an array list of all the users in the
group, and all the users in the sub groups, and what group they map to.
Arralist will look as follows:
|
User1
|
Group A
|
|
User2
|
Group A
|
|
User3
|
Group A
|
|
User4
|
Group B
|
|
User 5
|
Group B
|
This allows you to see what groups a user in part of in
Active Directory.
LDAPManager.FindMembership(“user1”);
This will list all the groups, that a user is a member of
directly and indirectly.
Or
oUser.FindMemberships()