简体   繁体   中英

Asp.Net Core - Identity SignInManager - How to signIn with an additional conditions in order for users to login (ex: ClientId, UserName and Password))

How to sign-in with an extra condition , in Asp.Net Core - Identity SignInManager

Example i want to check and validate ClientId , UserName and Password for sign-in.

some thing like this

var result = await SignInManager.PasswordSignInAsync(model.ClientId, model.Email, model.Password, model.RememberMe, shouldLockout: false);

Please see the full code bellow

        public async Task<IActionResult> OnPostAsync(string returnUrl = null)
        {
            returnUrl = returnUrl ?? Url.Content("~/");

            if (ModelState.IsValid)
            {
                // This doesn't count login failures towards account lockout
                // To enable password failures to trigger account lockout, set lockoutOnFailure: true
                var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);

                if (result.Succeeded)
                {
                    _logger.LogInformation("User logged in.");
                    return LocalRedirect(returnUrl);
                }
                if (result.RequiresTwoFactor)
                {
                    return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe });
                }
                if (result.IsLockedOut)
                {
                    _logger.LogWarning("User account locked out.");
                    return RedirectToPage("./Lockout");
                }
                else
                {
                    ModelState.AddModelError(string.Empty, "Invalid login attempt.");
                    return Page();
                }
            }

            // If we got this far, something failed, redisplay form
            return Page();
        }```

I will recommend using an adapter pattern approach by writing an interface and wrapper class that implements the interface over the original SignInManager.PasswordSignInAsync.

This wrapper class will have a method that takes in client id along with the rest of the parameters, perform validation, and then call SignInManager.PasswordSignInAsync once done.

Your login method will call the wrapper class through the interface using. netCore dependency injection through startup.cs.

public interface ISignInManagerAdapter
{
    Task<Microsoft.AspNetCore.Identity.SignInResult>  PasswordWithClientIdSignInAsync(string clientId, string userName, string password, bool isPersistent, bool lockoutOnFailure);
}

public class SignInManagerAdapter
{ 
    private readonly IClientValidatorService _clientValidatorService;
    public SignInManagerAdapter(IClientValidatorService clientValidatorService)
    {
       //you can add dependency injection interfaces to constructor parameter like below example.
       this._clientValidatorService = clientValidatorService;
    }
    public async Task<Microsoft.AspNetCore.Identity.SignInResult>  PasswordWithClientIdSignInAsync(string clientId, string userName, string password, bool isPersistent, bool lockoutOnFailure)
    {
        var validationStatus = _clientValidatorService.ValidateClientId(clientId);
        if (validationStatus == "Active")
        {
           var result = await SignInManager.PasswordSignInAsync(model.ClientId, model.Email, model.Password, model.RememberMe, shouldLockout: false);
           //do something
        }
        else
        {
           //do something
        }
    }
}

Their is more than one solution found, and i picked to extend the signInManager.
The above answer by @Markuzy is also correct, https://stackoverflow.com/a/61211905/13305109

Here is my code

public class MySignInManager<TUser> : SignInManager<MyUser> where TUser : class
{
    private readonly UserManager<MyUser> _userManager;
    private readonly MyContext _dbContext;
    private readonly IHttpContextAccessor _contextAccessor;

    public MySignInManager(UserManager<MyUser> userManager, IHttpContextAccessor contextAccessor, IUserClaimsPrincipalFactory<MyUser> claimsFactory, IOptions<IdentityOptions> optionsAccessor, ILogger<SignInManager<MyUser>> logger, MyContext dbContext, IAuthenticationSchemeProvider schemeProvider, IUserConfirmation<MyUser> confirmation) : base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemeProvider, confirmation)
    {
        _userManager = userManager ?? throw new ArgumentNullException(nameof(userManager));
        _contextAccessor = contextAccessor ?? throw new ArgumentNullException(nameof(contextAccessor));
        _dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
    }

    public override async Task<SignInResult> PasswordSignInAsync(string userName, string password, bool isPersistent, bool lockoutOnFailure)
    {
        SignInResult signInResult = new SignInResult();

        //Login not allowed - ClientId required to login
        return await Task.FromResult(signInResult);
    }

    public async Task<SignInResult> PasswordSignInAsync(string clientId, string userName, string password, bool isPersistent, bool lockoutOnFailure)
    {      
        if(CheckIsClientIdValid(username, password))
        {
            var result = await base.PasswordSignInAsync(userName, password, isPersistent, lockoutOnFailure);
            return result;
        }
        else
        {
            SignInResult result = await Task.FromResult(new SignInResult());
            //Login not allowed - ClientId mismatch
            return result;
        }            
    }
}

And add bellow code in Startup.cs according to the order

services.AddSignInManager<MySignInManager<MyUser>>();

And use as

var result = await _signInManager.PasswordSignInAsync(Input.ClientId, Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM