public async Task <ActionResult> Login([FromForm] Login login, [FromQuery] string returnUrl) { TryValidateModel(login); // This required for populate fields on form on post-back WorkContext.Form = Form.FromObject(login); if (!ModelState.IsValid) { return(View("customers/login", WorkContext)); } login.UserName = login.UserName?.Trim(); var user = await _signInManager.UserManager.FindByNameAsync(login.UserName); if (user == null) { WorkContext.Form.Errors.Add(SecurityErrorDescriber.LoginFailed()); return(View("customers/login", WorkContext)); } if (!new CanUserLoginToStoreSpecification(user).IsSatisfiedBy(WorkContext.CurrentStore)) { if (login.ForceLoginToAccountStore) { var store = WorkContext.AllStores.First(x => x.Id == user.StoreId); var url = HttpContext.Request.GetEncodedUrl(); var redirectUrl = _urlBuilder.ToStoreAbsolute(url, store, store.DefaultLanguage); return(RedirectPreserveMethod(redirectUrl)); } WorkContext.Form.Errors.Add(SecurityErrorDescriber.UserCannotLoginInStore()); return(View("customers/login", WorkContext)); } if (new IsUserLockedOutSpecification().IsSatisfiedBy(user)) { return(View("lockedout", WorkContext)); } if (new IsUserSuspendedSpecification().IsSatisfiedBy(user)) { WorkContext.Form.Errors.Add(SecurityErrorDescriber.AccountIsBlocked()); return(View("customers/login", WorkContext)); } var loginResult = await _signInManager.PasswordSignInAsync(login.UserName, login.Password, login.RememberMe, lockoutOnFailure : true); if (loginResult.Succeeded) { await _publisher.Publish(new UserLoginEvent(WorkContext, user)); if (new IsUserPasswordExpiredSpecification().IsSatisfiedBy(user)) { //the sign in operation doesn't change the current request user principal, this only happens on incoming requests when the cookie or bearer token is set. //Need to manually set User in the HttpContext to avoid issues such as Antiforegery cookies generated for anonymous within this request despite the user has already signed in. HttpContext.User = await _signInManager.ClaimsFactory.CreateAsync(user); WorkContext.Form = Form.FromObject(new ResetPassword { Token = await _signInManager.UserManager.GenerateUserTokenAsync(user, TokenOptions.DefaultProvider, "ResetPassword"), Email = user.Email, UserName = user.UserName }); return(View("customers/reset_password", WorkContext)); } return(StoreFrontRedirect(returnUrl)); } if (loginResult.RequiresTwoFactor) { var selectedProvider = _options.TwoFactorAuthenticationNotificationGateway; var userManager = _signInManager.UserManager; var code = await userManager.GenerateTwoFactorTokenAsync(user, selectedProvider); if (string.IsNullOrWhiteSpace(code)) { WorkContext.Form.Errors.Add(SecurityErrorDescriber.OperationFailed()); return(View("customers/login", WorkContext)); } NotificationBase twoFactorNotification = null; var veryfyCodeViewModel = new VerifyCodeViewModel { Provider = selectedProvider, ReturnUrl = returnUrl, RememberMe = login.RememberMe, Username = login.UserName }; if (veryfyCodeViewModel.Provider.EqualsInvariant("Phone")) { var phoneNumber = await userManager.GetPhoneNumberAsync(user); if (string.IsNullOrEmpty(phoneNumber)) { // Do not tell we have this user without phone WorkContext.Form.Errors.Add(SecurityErrorDescriber.OperationFailed()); return(View("customers/login", WorkContext)); } twoFactorNotification = new TwoFactorSmsNotification(WorkContext.CurrentStore.Id, WorkContext.CurrentLanguage) { Token = code, Recipient = phoneNumber, }; } else // "Email" { twoFactorNotification = new TwoFactorEmailNotification(WorkContext.CurrentStore.Id, WorkContext.CurrentLanguage) { Token = code, Sender = WorkContext.CurrentStore.Email, Recipient = GetUserEmail(user) }; } var sendingResult = await SendNotificationAsync(twoFactorNotification); if (sendingResult.IsSuccess != true) { WorkContext.Form.Errors.Add(SecurityErrorDescriber.ErrorSendNotification(sendingResult.ErrorMessage)); return(View("customers/login", WorkContext)); } WorkContext.Form = Form.FromObject(veryfyCodeViewModel); return(View("customers/verify_code", WorkContext)); } WorkContext.Form.Errors.Add(SecurityErrorDescriber.LoginFailed()); return(View("customers/login", WorkContext)); }
public async Task <ActionResult> Login([FromForm] Login login, string returnUrl) { TryValidateModel(login); // This required for populate fields on form on post-back WorkContext.Form = Form.FromObject(login); if (!ModelState.IsValid) { return(View("customers/login", WorkContext)); } login.UserName = login.UserName?.Trim(); var loginResult = await _signInManager.PasswordSignInAsync(login.UserName, login.Password, login.RememberMe, lockoutOnFailure : true); if (loginResult.Succeeded) { var user = await _signInManager.UserManager.FindByNameAsync(login.UserName); // Check that current user can sing in to current store if (new CanUserLoginToStoreSpecification(user).IsSatisfiedBy(WorkContext.CurrentStore) && new IsUserSuspendedSpecification().IsSatisfiedBy(user) == false) { await _publisher.Publish(new UserLoginEvent(WorkContext, user)); return(StoreFrontRedirect(returnUrl)); } else { WorkContext.Form.Errors.Add(SecurityErrorDescriber.UserCannotLoginInStore()); await _signInManager.SignOutAsync(); loginResult = Microsoft.AspNetCore.Identity.SignInResult.NotAllowed; } } if (loginResult.RequiresTwoFactor) { var user = await _signInManager.UserManager.FindByNameAsync(login.UserName); if (user == null) { WorkContext.Form.Errors.Add(SecurityErrorDescriber.OperationFailed()); return(View("customers/login", WorkContext)); } var selectedProvider = _options.TwoFactorAuthenticationNotificationGateway; var userManager = _signInManager.UserManager; var code = await userManager.GenerateTwoFactorTokenAsync(user, selectedProvider); if (string.IsNullOrWhiteSpace(code)) { WorkContext.Form.Errors.Add(SecurityErrorDescriber.OperationFailed()); return(View("customers/login", WorkContext)); } NotificationBase twoFactorNotification = null; var veryfyCodeViewModel = new VerifyCodeViewModel { Provider = selectedProvider, ReturnUrl = returnUrl, RememberMe = login.RememberMe, Username = login.UserName }; if (veryfyCodeViewModel.Provider.EqualsInvariant("Phone")) { var phoneNumber = await userManager.GetPhoneNumberAsync(user); if (string.IsNullOrEmpty(phoneNumber)) { // Do not tell we have this user without phone WorkContext.Form.Errors.Add(SecurityErrorDescriber.OperationFailed()); return(View("customers/login", WorkContext)); } twoFactorNotification = new TwoFactorSmsNotification(WorkContext.CurrentStore.Id, WorkContext.CurrentLanguage) { Token = code, Recipient = phoneNumber, }; } else // "Email" { twoFactorNotification = new TwoFactorEmailNotification(WorkContext.CurrentStore.Id, WorkContext.CurrentLanguage) { Token = code, Sender = WorkContext.CurrentStore.Email, Recipient = GetUserEmail(user) }; } var sendingResult = await SendNotificationAsync(twoFactorNotification); if (sendingResult.IsSuccess != true) { WorkContext.Form.Errors.Add(SecurityErrorDescriber.ErrorSendNotification(sendingResult.ErrorMessage)); return(View("customers/login", WorkContext)); } WorkContext.Form = Form.FromObject(veryfyCodeViewModel); return(View("customers/verify_code", WorkContext)); } if (loginResult.IsLockedOut) { return(View("lockedout", WorkContext)); } if (loginResult is CustomSignInResult signInResult && signInResult.IsRejected) { WorkContext.Form.Errors.Add(SecurityErrorDescriber.AccountIsBlocked()); } WorkContext.Form.Errors.Add(SecurityErrorDescriber.LoginFailed()); return(View("customers/login", WorkContext)); }