I am trying to learn how to use ASP.Net Identity. My scenario is that I have to authenticate against Active Directory. For that purpose I am trying to use ActiveDirecotoryMembershipProvider
. What I have to do is -
The way I did it is I configured in my web.config
to use ActiveDirectoryMembershipProvider
as default membership provider. Then I override PasswordSignInAsync
method in my ApplicationSignInManager
class (which inherits SignInManager
) as follows -
public override Task<SignInStatus> PasswordSignInAsync(string userName, string password, bool isPersistent, bool shouldLockout)
{
var adok = Membership.Provider.ValidateUser(userName, password);
if (adok)
{
var user = UserManager.FindByName(userName);
if (user == null)
return Task.FromResult<SignInStatus>(SignInStatus.Failure);
else
{
base.SignInAsync(user, isPersistent, shouldLockout);
return Task.FromResult<SignInStatus>(SignInStatus.Success);
}
}
else
return Task.FromResult<SignInStatus>(SignInStatus.Failure);
}
This seems to work. But I think it's not the right way to do it. Can anyone suggest any better way to achieve this?
Here is how I called the above mentioned
var result = await SignInManager.PasswordSignInAsync(username, password, isPersistent: false, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
return RedirectToAction("Index", "Home");
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Invalid login attempt.");
return View();
}
According to the answers I got, I should not call Membership Validate
method inside PasswordSignInAsync
. I agree with that. In fact, I think overriding the method is wrong as well.
It was also suggested that I use UserLogins
where I would give my AD an provider ID. But the only way I can think of using this is as follows -
IList<UserLoginInfo> loginInfos = await SignInManager.UserManager.GetLoginsAsync(username);
var valid = false;
foreach(var info in loginInfos)
{
valid = Membership.Providers[info.ProviderKey].ValidateUser(username, password);
if (valid) break;
}
So, if I want to authenticate an user against multiple Providers I can create provider key for each of them and assign those provider keys to the users. And this code will validate the user against them. But where should I put this code? What convention should I follow?
I am not keen on coding the AD validation myself because I think ActiveDirectoryMembershipProvider
can do a better job than my own code. Also for both cases I have to add reference to System.DirectoryServices
anyway.
You don't want to mix MembershipProviders with identity. What you most likely want to do, is treat logging into ActiveDirectory similar to how identity treats other external logins (like google/facebook).
This basically boils down to storing the AD username as a login:
userManager.AddLogin(<userId>, new UserLoginInfo("ActiveDirectory", "<ADUserName>")
If you only login via AD, then you could indeed override PasswordSignIn to explicitly validate against AD
Otherwise, you'd want this in only the specific login flow for AD, preserving the existing local password/social login functionality.
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