Example #1
0
        public virtual async Task <IActionResult> VerifyEmail(Guid userId)
        {
            var info = await AccountService.GetEmailVerificationInfo(userId);

            if (info.User == null)
            {
                return(this.RedirectToSiteRoot(CurrentSite));
            }

            if (info.User.EmailConfirmed)
            {
                return(this.RedirectToSiteRoot(CurrentSite));
            }

            var callbackUrl = Url.Action("ConfirmEmail", "Account",
                                         new { userId = info.User.Id.ToString(), code = info.EmailVerificationToken },
                                         protocol: HttpContext.Request.Scheme);

            EmailSender.SendAccountConfirmationEmailAsync(
                CurrentSite,
                info.User.Email,
                StringLocalizer["Confirm your account"],
                callbackUrl,
                info.EmailVerificationToken
                ).Forget();

            await IpAddressTracker.TackUserIpAddress(CurrentSite.Id, info.User.Id);

            return(RedirectToAction("EmailConfirmationRequired", new { userId = info.User.Id, didSend = true }));
        }
Example #2
0
        protected async Task <IActionResult> HandleLoginSuccess(UserLoginResult result, string returnUrl)
        {
            Analytics.HandleLoginSuccess(result).Forget();

            if (result.User != null)
            {
                await IpAddressTracker.TackUserIpAddress(CurrentSite.Id, result.User.Id);
            }

            if (!string.IsNullOrEmpty(returnUrl))
            {
                // when site is closed login is still allowed
                // but don't redirect to closed paged
                if (
                    (!returnUrl.Contains("/closed")) &&
                    (!returnUrl.Contains("/oops/error")) &&
                    (!returnUrl.Contains("/account/logout"))
                    )
                {
                    return(LocalRedirect(returnUrl));
                }
            }

            return(this.RedirectToSiteRoot(CurrentSite));
        }
Example #3
0
        private async Task <IActionResult> HandleLoginSuccess(UserLoginResult result, string returnUrl)
        {
            if (result.User != null)
            {
                await ipAddressTracker.TackUserIpAddress(Site.Id, result.User.Id);
            }

            if (!string.IsNullOrEmpty(returnUrl))
            {
                // when site is closed login is still allowed
                // but don't redirect to closed paged
                if (!returnUrl.Contains("/closed"))
                {
                    return(LocalRedirect(returnUrl));
                }
            }

            return(this.RedirectToSiteRoot(Site));
        }
Example #4
0
        protected async Task <IActionResult> HandleLoginNotAllowed(UserLoginResult result, string returnUrl)
        {
            Analytics.HandleLoginNotAllowed(result).Forget();

            if (result.User != null)
            {
                await IpAddressTracker.TackUserIpAddress(CurrentSite.Id, result.User.Id);

                if (result.NeedsEmailConfirmation)
                {
                    if (ShouldSendConfirmation(result.User))
                    {
                        var callbackUrl = Url.Action(new UrlActionContext
                        {
                            Action     = "ConfirmEmail",
                            Controller = "Account",
                            Values     = new { userId = result.User.Id.ToString(), code = result.EmailConfirmationToken, returnUrl },
                            Protocol   = HttpContext.Request.Scheme
                        });

                        EmailSender.SendAccountConfirmationEmailAsync(
                            CurrentSite,
                            result.User.Email,
                            StringLocalizer["Confirm your account"],
                            callbackUrl,
                            result.EmailConfirmationToken
                            ).Forget();


                        this.AlertSuccess(StringLocalizer["Please check your email inbox, we just sent you a link that you need to click to confirm your account"], true);
                    }

                    return(RedirectToAction("EmailConfirmationRequired", new { userId = result.User.Id, didSend = true, returnUrl }));
                }

                if (result.NeedsAccountApproval)
                {
                    var timeSpan = DateTime.UtcNow - result.User.CreatedUtc;
                    if (timeSpan.TotalDays < 1)
                    {
                        // account was just created so send notification to approver
                        EmailSender.AccountPendingApprovalAdminNotification(CurrentSite, result.User).Forget();
                    }

                    return(RedirectToAction("PendingApproval", new { userId = result.User.Id, didSend = true }));
                }
            }

            return(this.RedirectToSiteRoot(CurrentSite));
        }
Example #5
0
        protected async Task <IActionResult> HandleLockout(UserLoginResult result = null)
        {
            Analytics.HandleLockout(result).Forget();

            ViewData["Title"] = StringLocalizer["Locked out"];

            if (result != null && result.User != null)
            {
                await IpAddressTracker.TackUserIpAddress(CurrentSite.Id, result.User.Id);

                Log.LogWarning($"redirecting to lockout page for {result.User.Email} because account is locked");
            }

            return(View("Lockout"));
        }
Example #6
0
        protected async Task <IActionResult> HandleRequiresTwoFactor(UserLoginResult result, string returnUrl, bool rememberMe)
        {
            Analytics.HandleRequiresTwoFactor(result).Forget();

            if (result.User != null)
            {
                await IpAddressTracker.TackUserIpAddress(CurrentSite.Id, result.User.Id);

                Log.LogWarning($"redirecting from login for {result.User.Email} because 2 factor not configured yet for account");
            }

            return(RedirectToAction(nameof(LoginWith2fa), new { returnUrl, rememberMe }));

            //return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl, RememberMe = rememberMe });
        }
Example #7
0
        public async Task <IActionResult> Login(LoginViewModel model, string returnUrl = null)
        {
            ViewData["Title"]     = sr["Log in"];
            ViewData["ReturnUrl"] = returnUrl;
            if ((Site.CaptchaOnLogin) && (Site.RecaptchaPublicKey.Length > 0))
            {
                model.RecaptchaSiteKey = Site.RecaptchaPublicKey;
            }
            model.UseEmailForLogin           = Site.UseEmailForLogin;
            model.LoginInfoTop               = Site.LoginInfoTop;
            model.LoginInfoBottom            = Site.LoginInfoBottom;
            model.ExternalAuthenticationList = signInManager.GetExternalAuthenticationSchemes();
            // don't disable db auth if there are no social auth providers configured
            model.DisableDbAuth = Site.DisableDbAuth && Site.HasAnySocialAuthEnabled();

            if (!ModelState.IsValid)
            {
                return(View(model));
            }

            if ((Site.CaptchaOnLogin) && (Site.RecaptchaPublicKey.Length > 0))
            {
                var recpatchaSecretKey = Site.RecaptchaPrivateKey;
                var captchaResponse    = await this.ValidateRecaptcha(Request, recpatchaSecretKey);

                if (!captchaResponse.Success)
                {
                    ModelState.AddModelError("recaptchaerror", sr["reCAPTCHA Error occured. Please try again"]);
                    return(View(model));
                }
            }

            if (userManager.Site.RequireConfirmedEmail || userManager.Site.RequireApprovalBeforeLogin)
            {
                var user = await userManager.FindByNameAsync(model.Email);

                if (user != null)
                {
                    // TODO: showing these messages is not right
                    // this can be used by a hacker to determine that an account exists
                    // need to fix this
                    // probably all of these checks should be moved into signInManager.PasswordSignInAsync
                    // so that we either redirect to show message if login was correct credentials
                    // or just show invalid login attempt otherwise

                    if (userManager.Site.RequireConfirmedEmail)
                    {
                        if (!await userManager.IsEmailConfirmedAsync(user))
                        {
                            //ModelState.AddModelError(string.Empty, "You must have a confirmed email to log in.");
                            ModelState.AddModelError(string.Empty, sr["Invalid login attempt."]);
                            return(View(model));
                        }
                    }

                    if (userManager.Site.RequireApprovalBeforeLogin)
                    {
                        if (!user.AccountApproved)
                        {
                            //ModelState.AddModelError(string.Empty, "Your account must be approved by an administrator before you can log in. If an administrator approves your account, you will receive an email notifying you that your account is ready.");
                            ModelState.AddModelError(string.Empty, sr["Invalid login attempt."]);
                            return(View(model));
                        }
                    }

                    if ((user.IsLockedOut) || (user.IsDeleted))
                    {
                        //ModelState.AddModelError(string.Empty, "Your account must be approved by an administrator before you can log in. If an administrator approves your account, you will receive an email notifying you that your account is ready.");
                        ModelState.AddModelError(string.Empty, sr["Invalid login attempt."]);
                        return(View(model));
                    }
                }
            }

            var persistent = false;

            if (userManager.Site.AllowPersistentLogin)
            {
                //TODO: hide remember me in view if persistent login not allowed  site settings
                persistent = model.RememberMe;
            }

            Microsoft.AspNetCore.Identity.SignInResult result;
            if (Site.UseEmailForLogin)
            {
                result = await signInManager.PasswordSignInAsync(
                    model.Email,
                    model.Password,
                    persistent,
                    lockoutOnFailure : false);
            }
            else
            {
                result = await signInManager.PasswordSignInAsync(
                    model.UserName,
                    model.Password,
                    persistent,
                    lockoutOnFailure : false);
            }


            if (result.Succeeded)
            {
                SiteUser user;
                if (Site.UseEmailForLogin)
                {
                    user = await userManager.FindByNameAsync(model.Email);
                }
                else
                {
                    user = await userManager.FindByNameAsync(model.UserName);
                }

                if (user != null)
                {
                    await ipAddressTracker.TackUserIpAddress(Site.Id, user.Id);
                }

                if (!string.IsNullOrEmpty(returnUrl))
                {
                    return(LocalRedirect(returnUrl));
                }

                return(this.RedirectToSiteRoot(Site));
            }
            if (result.RequiresTwoFactor)
            {
                return(RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl, RememberMe = model.RememberMe }));
            }
            if (result.IsLockedOut)
            {
                return(View("Lockout"));
            }
            else
            {
                ModelState.AddModelError(string.Empty, sr["Invalid login attempt."]);
                return(View(model));
            }
        }
Example #8
0
        public async Task <IActionResult> Login(LoginViewModel model, string returnUrl = null)
        {
            ViewData["Title"]     = "Log in";
            ViewData["ReturnUrl"] = returnUrl;
            if ((Site.CaptchaOnLogin) && (Site.RecaptchaPublicKey.Length > 0))
            {
                model.RecaptchaSiteKey = Site.RecaptchaPublicKey;
            }

            model.LoginInfoTop    = Site.LoginInfoTop;
            model.LoginInfoBottom = Site.LoginInfoBottom;

            if (!ModelState.IsValid)
            {
                return(View(model));
            }

            if ((Site.CaptchaOnLogin) && (Site.RecaptchaPublicKey.Length > 0))
            {
                var recpatchaSecretKey = Site.RecaptchaPrivateKey;
                var captchaResponse    = await this.ValidateRecaptcha(Request, recpatchaSecretKey);

                if (!captchaResponse.Success)
                {
                    ModelState.AddModelError("recaptchaerror", "reCAPTCHA Error occured. Please try again");
                    return(View(model));
                }
            }

            if (userManager.Site.RequireConfirmedEmail || userManager.Site.RequireApprovalBeforeLogin)
            {
                var user = await userManager.FindByNameAsync(model.Email);

                if (user != null)
                {
                    // TODO: showing these messages is not right
                    // this can be used by a hacker to determine that an account exists
                    // need to fix this
                    // probably all of these checks should be moved into signInManager.PasswordSignInAsync
                    // so that we either redirect to show message if login was correct credentials
                    // or just show invalid login attempt otherwise

                    if (userManager.Site.RequireConfirmedEmail)
                    {
                        if (!await userManager.IsEmailConfirmedAsync(user))
                        {
                            ModelState.AddModelError(string.Empty, "You must have a confirmed email to log in.");
                            return(View(model));
                        }
                    }

                    if (userManager.Site.RequireApprovalBeforeLogin)
                    {
                        if (!user.AccountApproved)
                        {
                            ModelState.AddModelError(string.Empty, "Your account must be approved by an administrator before you can log in. If an administrator approves your account, you will receive an email notifying you that your account is ready.");
                            return(View(model));
                        }
                    }

                    if (user.IsLockedOut)
                    {
                        ModelState.AddModelError(string.Empty, "Your account must be approved by an administrator before you can log in. If an administrator approves your account, you will receive an email notifying you that your account is ready.");
                        return(View(model));
                    }
                }
            }


            //TODO: we don't want to lockout on first failure, we need something more advanced
            // based on sitesettings
            //var maxFailures = userManager.Site.MaxInvalidPasswordAttempts;
            // probably need to override signInManager.PasswordSignInAsync
            // or create a new method that does what we want
            // we also need to prevent login if site requires confirmed email
            // and user email is not confirmed
            // also need to prevent login if site requires approval before new users can login
            // and user is not yet approved
            // also need a UI to manually lockout a user


            // This doesn't count login failures towards account lockout
            // To enable password failures to trigger account lockout, change to lockoutOnFailure: true
            bool persistent = false;

            if (userManager.Site.AllowPersistentLogin)
            {
                //TODO: hide remember me in view if persistent login not allowed  site settings
                persistent = model.RememberMe;
            }

            //userManager.

            var result = await signInManager.PasswordSignInAsync(
                model.Email,
                model.Password,
                persistent,
                lockoutOnFailure : false);

            if (result.Succeeded)
            {
                var user = await userManager.FindByNameAsync(model.Email);

                if (user != null)
                {
                    await ipAddressTracker.TackUserIpAddress(Site.SiteGuid, user.UserGuid);
                }

                if (!string.IsNullOrEmpty(returnUrl))
                {
                    return(LocalRedirect(returnUrl));
                }

                return(this.RedirectToSiteRoot(Site));
            }
            if (result.RequiresTwoFactor)
            {
                return(RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl, RememberMe = model.RememberMe }));
            }
            if (result.IsLockedOut)
            {
                return(View("Lockout"));
            }
            else
            {
                ModelState.AddModelError(string.Empty, "Invalid login attempt.");
                return(View(model));
            }
        }