'How can I use ActiveDirectoryMembershipProvider with ASP.NET Identity?

I'm learning to use .NET Identity. I have to authenticate to Active Directory. For that purpose I am trying to use ActiveDirecotoryMembershipProvider. I have to:

  1. Authenticate user/password against Active Directory (AD).
  2. Check whether user is present in my own database.

I configured it in my web.config to use ActiveDirectoryMembershipProvider as the default membership provider. Then I overrode 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. Is there a 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 the 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 a user against multiple Providers, I can create a 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.



Solution 1:[1]

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.

Solution 2:[2]

Try it once following step, may be it will helpful you.

https://msdn.microsoft.com/en-us/library/ff650307.aspx

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Community
Solution 2 Ajay2707