I will start by describing how my application works today without LDAP. I have WPF application that consumes WCF services (authentication windows or UserName depends on users choice). This services allows communication with database.
I display to user a "Login screen" in order to allow him set her "user name" and "password" then application connects to service and consumes function that checks if UserName and Password exist in database. (see img below)
Now I need also to integrate LDAP for authenticating user accounts against their existing systems instead of having to create another login account.
I'm bit ignorant about LDAP and confused about many things. Please excuse the possible use of wrong terminology.
I googled but I still don't have answers of many questions.
1- What is the relation between users that exist in my database table "User" and profiles that I should be created in LDAP ?
2- What is the check I should do to allow user come from LDAP to access to my application and use all functionnalities of my service ?
3- Should I have service type "LDAP" like other authentications types I have today in my application ("Windows" and "UserName") ?
4- If I want to update my application architecture described in picture above where should I add LDAP ?
First I am going to answer your questions one by one,
The user on LDAP is the same on DB, you can hold LDAP's Username and it's domain in your Users Table, but the profile on the LDAP may vary with your profile table, but it can be fetched from LDAP address.
It's enough to check username and password over LDAP, just need to hold LDAP addresses in a Table (example ExternalPath) and make a relation between User and ExternalPath tables. LDAP address is contains some specifications.
Yes, you have to have a separate mechanism for identifying LDAP Users which I will explain more further.
This is not hard if everything be atomic and designed right, in further steps you may see it is easy.
So let me tell about my experience in LDAP and Authenticate users on LDAP and DB and our architecture.
I was implemented a WCF service named Auth.svc
, this service contains a method named AuthenticateAndAuthorizeUser
this is transparent for user which came from LDAP or anywhere.
I hope you get the clue and architecture to Authenticate user over LDAP and DB in below steps:
1- First I have a table named Users
which hold users info and one more field named ExternalPath
as foreign key, if it is null specify UserName is in DB wit it's password otherwise it is came from UserDirectory
.
2- In second step you have to hold LDAP address (in my case LDAP addresses are in ExternalPath
table), all LDAP addresses are on port 389
commonly.
3- Implementing authenticate User, if is not found(with Username and Password) then check it's ExternalPath
to verify over LDAP address.
4- The DB schema should be something like below screenshot.
As you can see ExternalPath
field specify user is from LDAP or not.
5- In presentation layer I am defining LDAP servers like below screenshot also
6- In the other side while adding new user in system you can define LDAP for user in my case I am listing LDAP titles in a DropDown in adding User form (if admin select LDAP address then don't need to get password and save it in DB), as I mentioned just need to hold LDAP username not password.
7- But last thing is authenticating user on LDAP and DB.
So the authenticate method is something like:
User userLogin = User.Login<User>(username, password, ConnectionString, LogFile);
if (userLogin != null)
return InitiateToken(userLogin, sourceApp, sourceAddress, userIpAddress);
else//Check it's LDAP path
{
User user = new User(ConnectionString, LogFile).GetUser(username);
if (user != null && user.ExternalPath != null)
{
LDAPSpecification spec = new LDAPSpecification
{
UserName = username,
Password = password,
Path = user.ExternalPath.Path,
Domain = user.ExternalPath.Domain
};
bool isAthenticatedOnLDAP = LDAPAuthenticateUser(spec);
}
}
If userLogin
does not exist in DB by entered UserName and Password then we should authenticate it over related LDAP address.
In else
block find User from Users table and get it's ExternalPath
if this field was not null means User is on LDAP.
8- The LDAPAuthenticateUser
method is :
public bool LDAPAuthenticateUser(LDAPSpecification spec)
{
string pathDomain = string.Format("LDAP://{0}", spec.Path);
if (!string.IsNullOrEmpty(spec.Domain))
pathDomain += string.Format("/{0}", spec.Domain);
DirectoryEntry entry = new DirectoryEntry(pathDomain, spec.UserName, spec.Password, AuthenticationTypes.Secure);
try
{
//Bind to the native AdsObject to force authentication.
object obj = entry.NativeObject;
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(SAMAccountName=" + spec.UserName + ")";
search.PropertiesToLoad.Add("cn");
SearchResult result = search.FindOne();
if (null == result)
{
return false;
}
}
catch (Exception ex)
{
Logging.Log(LoggingMode.Error, "Error authenticating user on LDAP , PATH:{0} , UserName:{1}, EXP:{2}", pathDomain, spec.UserName, ex.ToString());
return false;
}
return true;
}
If exception raised in LDAPAuthenticateUser
means User does not exist in User Directory.
The authentication code accepts a domain, a user name, a password, and a path to the tree in the Active Directory.
The above code uses the LDAP directory provider the authenticate method calls LDAPAuthenticateUser
and passes in the credentials that are collected from the user. Then, a DirectoryEntry object is created with the path to the directory tree, the user name, and the password. The DirectoryEntry
object tries to force the AdsObject
binding by obtaining the NativeObject
property. If this succeeds, the CN
attribute for the user is obtained by creating a DirectorySearcher
object and by filtering on the SAMAccountName
. After the user is authenticated and exception not happened method returns true means user find on given LDAP address.
To see more info about Lightweight Directory Access Protocol and authenticate over it THIS Link can be useful which tells about specification more.
Hope will help you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With