I´m building a web application which could get accessed in two ways. Everyone who is working in the same organisation as I can use our active directory to access the application.
Everyone from outside should join the application through a separate membership database. Everyone should have a account in the membership database with his roles, so the ad connection is just a bonus to make it easier to keep the password and username in mind.
I searched the internet but couldn't find a comparable situation. This is my first time working with ad.
Does anyone know of a framework that can be used or give me a hint on how I could try to solve the problem?
At moment I implemented the membership connection with System.Web.WebData.SimpleMembershipProvider
and it works fine.
In the later development of the application I also need some other connections to the ad to check some information but that is just a problem for another day.
Thanks for the help.
Open up your web.config.
First of all you'll need connectionString for your ActiveDirectory:
<connectionStrings>
...
<add name="ADConnectionString" connectionString=LDAP://*adserver*/DC=*domain* />
...
</connectionStrings>
Scroll down to the <membership>
tag. Make sure you have defaultProvider attribute set for the <membership>
, like:
<membership defaultProvider="SimpleMembershipProvider">
Then add new provider for AD members inside <providers>
:
<add name="ADMembershipProvider" type="System.Web.Security.ActiveDirectoryMembershipProvider" connectionStringName="ADConnectionString" attributeMapUsername="sAMAccountName" />
That should do the trick for web.config. Now we need to auth AD users on Log in. Go to your AccountController Login action. First we try to authenticate user via ActiveDirectory, there is handy class called PrincipalContext
in System.DirectoryServices.AccountManagement
namespace. If that fails we use the default membership provider:
public ActionResult Login(LoginModel model, string returnUrl)
{
try
{
// try to auth user via AD
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain))
{
if (pc.ValidateCredentials(model.UserName, model.Password))
{
FormsAuthentication.SetAuthCookie(model.UserName, false);
return RedirectToAction("Index", "Home");
}
}
// try the default membership auth if active directory fails
if (Membership.ValidateUser(model.UserName, model.Password))
{
FormsAuthentication.SetAuthCookie(model.UserName, false);
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "Login failed");
}
}
catch
{
}
GetErrorsFromModelState();
return View(model);
}
For your later requirements you can get the current logged in ActiveDirectory user with UserPrincipal class:
using (var context = new PrincipalContext( ContextType.Domain))
{
using (var aduser = UserPrincipal.FindByIdentity( context,IdentityType.SamAccountName, HttpContext.User.Identity.Name))
{
...
}
}
Hope this helps and I didn't miss anything.
This Code will give you if the user with specified username and password is valid
public bool ValidateUser(string userName, string password)
{
bool authenticated = false;
string dePath = string.Empty;
dePath += DomainController;
if (!string.IsNullOrEmpty(BaseDomainName))
{
dePath += "/" + BaseDomainName;
}
try
{
DirectoryEntry entry = new DirectoryEntry(dePath, userName, password);
object nativeObject = entry.NativeObject;
authenticated = true;
}
catch
{
return false;
}
return authenticated;
}
You can add DomainController and BaseDomainName in web.config appSettings as keys