Example #1
0
        public async Task <IActionResult> Login([FromBody] SessionCreateForm form)
        {
            // El form está comlpeto? --------------------
            if (form == null)
            {
                return(new BadRequestResult());
            }

            if (string.IsNullOrEmpty(form.UsernameOrEmail))
            {
                ModelState.AddModelError(nameof(form.UsernameOrEmail), "Required");
            }

            if (string.IsNullOrEmpty(form.Password))
            {
                ModelState.AddModelError(nameof(form.Password), "Required");
            }

            if (!ModelState.IsValid)
            {
                return(ValidationError());
            }

            // La IP tiene permiso de intentar login? --------------------
            var attemptRateResult = await LoginAttemptLimitingService.Check(RequestInfoService.RemoteIp, LoginAttemptStore);

            if (!attemptRateResult.IsApproved)
            {
                ModelState.AddModelError("", attemptRateResult.ErrorMessage);
                return(ValidationError());
            }

            LoginAttempt attempt = new LoginAttempt(this.RequestInfoService.RemoteIp, DateTime.UtcNow);

            // La credencial existe? --------------------
            string failedLoginMsg = "Invalid email and password combination.";

            Credential credential = null;
            bool       isEmail    = form.UsernameOrEmail.IsEmail();

            if (isEmail)
            {
                credential = await CredentialStore.GetByEmail(form.UsernameOrEmail);
            }
            else
            {
                credential = await CredentialStore.Get(form.UsernameOrEmail);
            }


            if (credential == null)
            {
                ModelState.AddModelError("", failedLoginMsg);
                await LoginAttemptStore.Create(attempt);

                return(ValidationError());
            }

            // La contraseña es correcta?
            string newCalculatedHash = HashingUtil.GenerateHash(form.Password, credential.PasswordSalt);

            if (newCalculatedHash != credential.PasswordHash)
            {
                ModelState.AddModelError("", failedLoginMsg);
                await LoginAttemptStore.Create(attempt);

                return(ValidationError());
            }

            // El usuario está penalizado?
            CredentialPenalty activePenalty = await CredentialPenaltyStore.Get(credential.CredentialId, DateTime.UtcNow);

            if (activePenalty != null)
            {
                string validationMsg = null;

                if (activePenalty.EndDate.HasValue)
                {
                    validationMsg = string.Format("User temporarily banned, until [{0}]. Reason: '{1}'", activePenalty.EndDate.Value.ToString(), activePenalty.Reason);
                }
                else
                {
                    validationMsg = string.Format("User permanently banned. Reason: '{0}'", activePenalty.Reason);
                }

                ModelState.AddModelError("", validationMsg);
                await LoginAttemptStore.Create(attempt);

                return(ValidationError());
            }

            var agent = RequestInfoService.UserAgent;

            // La credencial ya tiene una sesión activa?
            Session session =
                await this.SessionStore.Get(
                    credential.CredentialId,
                    agent.DeviceClass,
                    agent.DeviceName,
                    agent.AgentName,
                    agent.AgentVersion);

            if (session != null)
            {
                session.LastActiveDate = DateTime.UtcNow;

                if (session.AllowSelfRenewal)
                {
                    session.ExpirationDate = session.LastActiveDate.AddDays(1);
                }

                await SessionStore.Update(session);
            }
            else
            {
                // Crea la sesión
                session = new Session();
                session.CredentialId     = credential.CredentialId;
                session.LoginDate        = DateTime.UtcNow;
                session.ExpirationDate   = DateTime.UtcNow.AddDays(1);
                session.LastActiveDate   = session.LoginDate;
                session.AllowSelfRenewal = form.IsRememberLogin;
                session.Device           = new UserDevice(agent.DeviceClass, agent.DeviceName);
                session.Agent            = new UserAgent(agent.AgentName, agent.AgentVersion);

                await SessionStore.Create(session);
            }

            // Autentifica
            // check if we are in the context of an authorization request
            var context = await _interaction.GetAuthorizationContextAsync(form.ReturnUrl);

            await _events.RaiseAsync(new UserLoginSuccessEvent(credential.DisplayName, credential.CredentialId, credential.DisplayName, clientId : context?.ClientId));

            // only set explicit expiration here if user chooses "remember me".
            // otherwise we rely upon expiration configured in cookie middleware.
            AuthenticationProperties props = null;

            if (form.IsRememberLogin)
            {
                props = new AuthenticationProperties
                {
                    IsPersistent = true,
                    ExpiresUtc   = DateTimeOffset.UtcNow.Add(TimeSpan.FromHours(8))
                };
            }
            ;

            // issue authentication cookie with subject ID and username
            var isuser = new IdentityServerUser(credential.CredentialId)
            {
                DisplayName = credential.DisplayName
            };

            await HttpContext.SignInAsync(isuser, props);

            // Devuelve el recurso Session
            return(Element <Session>(session));
        }