namespace weblogint2.Areas.Identity.Data
{
public partial class AuthSignInManager<TUser> : SignInManager<ApplicationUser> where TUser : class
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly weblogint2Context _db;
private readonly IHttpContextAccessor _contextAccessor;
IUserClaimsPrincipalFactory<ApplicationUser> _claimsFactory;
public AuthSignInManager(
UserManager<ApplicationUser> userManager,
IHttpContextAccessor contextAccessor,
IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory,
IOptions<IdentityOptions> optionsAccessor,
ILogger<SignInManager<ApplicationUser>> logger,
weblogint2Context dbContext,
IAuthenticationSchemeProvider schemes,
IUserConfirmation<ApplicationUser> confirmation)
: base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes, confirmation)
{
_userManager = userManager ?? throw new ArgumentNullException(nameof(userManager));
_contextAccessor = contextAccessor ?? throw new ArgumentNullException(nameof(contextAccessor));
_db = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
_claimsFactory = claimsFactory;
}
public override async Task<SignInResult> PasswordSignInAsync(string userName, string password, bool isPersistent, bool shouldLockout)
{
// WHAT AM I MISSING HERE?
if (userName.ToLower() == "[email protected]" && password.ToLower() == "111111111@")
{
return await Task.FromResult(SignInResult.TwoFactorRequired);
}
else
if (userName.ToLower() == "[email protected]" && password.ToLower() == "111111111@")
{
return await Task.FromResult(SignInResult.Success);
}
else
{
return await Task.FromResult(SignInResult.Failed);
}
}
public override async Task<SignInResult> TwoFactorAuthenticatorSignInAsync(string code, bool isPersistent, bool rememberClient)
{
var results = Task.FromResult(SignInResult.Failed);
string GeneratedCode = "124578";
if (string.IsNullOrEmpty(code))
return await Task.FromResult(SignInResult.Failed);
else if(string.Equals(code,GeneratedCode))
{
return await Task.FromResult(SignInResult.Success);
}
else
{
return await Task.FromResult(SignInResult.Failed);
}
}
}
}
At Login Page
var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, Input.Email)
};
}
if (result.RequiresTwoFactor)
{
// control is commine here
var currentUser = await _userManager.FindByEmailAsync(Input.Email);
return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl });//, RememberMe = Input.RememberMe}) ;
}
At Loginwith2f page
public async Task<IActionResult> OnGetAsync(bool rememberMe, string returnUrl = null)
{
// Ensure the user has gone through the username & password screen first
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
if (user == null)
{
throw new InvalidOperationException($"Unable to load two-factor authentication user.");
// NULL HAPPENS HERE
}
ReturnUrl = returnUrl;
RememberMe = rememberMe;
return Page();
}
ApplicationUser class
public class ApplicationUser : IdentityUser
{
[PersonalData]
[Column(TypeName ="nvarchar(100)")]
public string FirstName { get; set; }
[PersonalData]
[Column(TypeName = "nvarchar(100)")]
public string LastName { get; set; }
[PersonalData]
[Column(TypeName = "bit")]
public bool IsSystemAdministrator { get; set; }
}
At Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<SignInManager<ApplicationUser>, AuthSignInManager<ApplicationUser>>();
}
've implemented custom AuthSignInManager class when page is redirected to LoginWith2fa. I get null at await _signInManager.GetTwoFactorAuthenticationUserAsync();
TLDR
You're overwriting SignInManager<T> however the functionality you are trying to replace are interfaces themselves. You can replaced the user validation (via IUserValidator) and claims creation (via IClaimsTransformation) logic with their specific interfaces allowing the SignInManager<T> to function as normal.
Explanation
There are a few issues with your code, here are two of the most relevant:
AuthSignInManager<TUser> never actually signs the user in. Typically the act of signing a user in done via one of the AuthenticationHttpContextExtensions (example: HttpContext.SignInAsync(...))Based on what it seems from your code you are trying to validate user credentials (username and password), append additional claims when credentials are valid, then conditionally continue with the two step verification process.
ASP.NET Core Identity offers ability to easily implement custom code for specifically these tasks. Here are the interfaces needed to implement:
PasswordSignInAsync() implementation from AuthSignInManager and instead implement a custom instance of IUserValidator to validate user credentials.ConfigureServices() within Startup.cs. Also remove the registration of your AuthSignInManager<ApplicationUser> from ConfigureServices().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