Esempio n. 1
0
        public async Task ResetPasswordAsync(ILoginProcess process, string newPassword)
        {
            var session = EntityHelper.GetSession(process);
            var ctx     = session.Context;

            ctx.ThrowIf(process.Status != LoginProcessStatus.Active, ClientFaultCodes.InvalidAction, "ProcessStatus", "Process is not active.");
            if (process.ExpiresOn < App.TimeService.UtcNow)
            {
                process.Status = LoginProcessStatus.Expired;
                session.SaveChanges();
                ctx.ThrowIf(true, ClientFaultCodes.InvalidAction, "Process", "Process expired.");
            }
            ctx.ThrowIf(process.ProcessType != LoginProcessType.PasswordReset, ClientFaultCodes.InvalidValue, "ProcessType", "Invalid login process type.");
            ctx.ThrowIf(process.PendingFactors != ExtraFactorTypes.None, ClientFaultCodes.InvalidAction, "PendingSteps", "The login process has verification steps pending");
            //Ok, we're ready
            var login = process.Login;

            ChangeUserPassword(login, newPassword, oneTimeByAdmin: false); //will log incident and fire event
            login.Flags &= ~LoginFlags.Suspended;                          //clear Suspended flag
            //complete process
            process.Status = LoginProcessStatus.Completed;
            session.SaveChanges();
            //Send notification
            var factor = FindLoginFactor(login, ExtraFactorTypes.Email);

            process.CurrentFactor = factor;
            session.SaveChanges();
            if (factor != null && _settings.MessagingService != null)
            {
                await _settings.MessagingService.SendMessage(ctx, LoginMessageType.PasswordResetCompleted, factor, process);
            }
        }
Esempio n. 2
0
        public void SendPin(ILoginProcess process, ILoginExtraFactor factor, string factorValue = null, string pin = null)
        {
            Util.Check(process.Login == factor.Login, "LoginProcess tries to use login factor not assigned to process's login.");
            var session       = EntityHelper.GetSession(process);
            var activeAlready = GetActiveConfirmationProcesses(factor, LoginProcessType.FactorVerification);

            session.Context.ThrowIf(activeAlready.Count > 2, ClientFaultCodes.InvalidAction, "Factor",
                                    "Cannot send pin - several pins already sent and are waiting for confirmation.");
            process.CurrentFactor = factor;
            if (factor.FactorType == ExtraFactorTypes.GoogleAuthenticator)
            {
                //do not generate or send pin
            }
            else
            {
                pin = pin ?? _settings.PinGenerator(process, factor);
                //login factor may be coming from user (password reset), or from factor record (verify email)
                if (string.IsNullOrWhiteSpace(factorValue))
                {
                    factorValue = factor.FactorValue;
                }
                process.CurrentPin = pin;
                SendPin(process, factor.FactorType, factorValue, pin);
            }
            session.SaveChanges();
            var logMsg = StringHelper.SafeFormat("Pin sent to user {0} using factor '{1}'. ", factor.Login.UserName, factorValue);

            OnLoginEvent(session.Context, LoginEventType.PinSent, factor.Login, logMsg);
        }
Esempio n. 3
0
        public bool CheckSecretQuestionAnswer(ILoginProcess process, ISecretQuestion question, string userAnswer)
        {
            var session = EntityHelper.GetSession(process);
            var qa      = process.Login.SecretQuestionAnswers.FirstOrDefault(a => a.Question == question);

            session.Context.ThrowIfNull(qa, ClientFaultCodes.InvalidValue, "question",
                                        "The question is not registered as user question. Question: {0}", question.Question);
            var match = CheckUserAnswer(qa, userAnswer);

            if (!match)
            {
                process.FailCount++;
                session.SaveChanges();
                OnLoginEvent(session.Context, LoginEventType.QuestionAnswersFailed, process.Login, "Secret questions check failed.");
                return(false);
            }
            // Add question number to list of answered questions in process record.
            // If all questions are answered, clear Pending step CheckQuestionAnswers
            var strAllAnswered  = process.AnsweredQuestions ?? string.Empty;
            var answeredNumbers = strAllAnswered.Split(',').Select(sn => sn.Trim()).ToList();
            var newAnsNum       = qa.Number.ToString();

            if (!answeredNumbers.Contains(newAnsNum))
            {
                answeredNumbers.Add(newAnsNum);
                process.AnsweredQuestions = string.Join(",", answeredNumbers);
                if (answeredNumbers.Count == process.Login.SecretQuestionAnswers.Count)
                {
                    //Set questions as answers
                    process.PendingFactors &= ~ExtraFactorTypes.SecretQuestions;
                }
                session.SaveChanges();
            }
            return(true);
        }
Esempio n. 4
0
        public bool CheckAllSecretQuestionAnswers(ILoginProcess process, IList <SecretQuestionAnswer> answers)
        {
            var  session = EntityHelper.GetSession(process);
            var  context = session.Context;
            bool result  = true;

            foreach (var qa in process.Login.SecretQuestionAnswers)
            {
                var ans = answers.FirstOrDefault(a => a.QuestionId == qa.Question.Id);
                if (ans == null)
                {
                    result = false; //question not answered
                }
                else
                {
                    result &= CheckUserAnswer(qa, ans.Answer);
                }
            }
            if (!result)
            {
                process.FailCount++;
                session.SaveChanges();
                OnLoginEvent(context, LoginEventType.QuestionAnswersFailed, process.Login, "Secret questions check failed.");
                return(false);
            }
            // Success
            // Save numbers of answered questions, clear flag in pending steps
            process.AnsweredQuestions = string.Join(",", process.Login.SecretQuestionAnswers.Select(qa => qa.Number));
            process.PendingFactors   &= ~ExtraFactorTypes.SecretQuestions;
            session.SaveChanges();
            OnLoginEvent(context, LoginEventType.QuestionAnswersSucceeded, process.Login, "Secret questions check succeeded.");
            return(result);
        }
Esempio n. 5
0
        public async Task SendPinAsync(ILoginProcess process, ILoginExtraFactor factor, string factorValue = null, string pin = null)
        {
            Util.Check(process.Login == factor.Login, "LoginProcess tries to use login factor not assigned to process's login.");
            var session       = EntityHelper.GetSession(process);
            var activeAlready = GetActiveConfirmationProcesses(factor, LoginProcessType.FactorVerification);

            session.Context.ThrowIf(activeAlready.Count > 2, ClientFaultCodes.InvalidAction, "Factor",
                                    "Cannot send pin - several pins already sent and are waiting for confirmation.");
            process.CurrentFactor = factor;
            if (factor.FactorType == ExtraFactorTypes.GoogleAuthenticator)
            {
                //do not generate or send pin
            }
            else
            {
                Util.Check(_settings.MessagingService != null, "Login messaging service not provided, cannot send pin.");
                pin = pin ?? _settings.PinGenerator(process, factor);
                if (string.IsNullOrWhiteSpace(factorValue))
                {
                    factorValue = factor.FactorValue;
                }
                process.CurrentPin = pin;
                var logMsg = Util.SafeFormat("Pin sent to user {0} using factor '{1}'. ", factor.Login.UserName, factorValue);
                OnLoginEvent(session.Context, LoginEventType.PinSent, factor.Login, logMsg);
                await _settings.MessagingService.SendMessage(session.Context, LoginMessageType.Pin, factor, process);
            }
            session.SaveChanges();
        }
 public bool CheckAllSecretQuestionAnswers(ILoginProcess process, IList<SecretQuestionAnswer> answers)
 {
     var session = EntityHelper.GetSession(process);
       var context = session.Context;
       bool result = true;
       foreach(var qa in process.Login.SecretQuestionAnswers) {
     var ans = answers.FirstOrDefault(a => a.QuestionId == qa.Question.Id);
     if(ans == null)
       result = false ; //question not answered
     else
       result &= CheckUserAnswer(qa, ans.Answer);
       }
       if(!result) {
     process.FailCount++;
     session.SaveChanges();
     OnLoginEvent(context, LoginEventType.QuestionAnswersFailed, process.Login, "Secret questions check failed.");
     LogIncident(context, LoginIncidentType, "InvalidQuestionAnswer",
     "Invalid answer(s) to secret questions, user: "******",", process.Login.SecretQuestionAnswers.Select(qa => qa.Number));
       process.PendingFactors &= ~ExtraFactorTypes.SecretQuestions;
       session.SaveChanges();
       OnLoginEvent(context, LoginEventType.QuestionAnswersSucceeded, process.Login, "Secret questions check succeeded.");
       return result;
 }
Esempio n. 7
0
        public void ResetPassword(ILoginProcess process, string newPassword)
        {
            var session = EntityHelper.GetSession(process);
            var ctx     = session.Context;

            ctx.ThrowIf(process.Status != LoginProcessStatus.Active, ClientFaultCodes.InvalidAction, "ProcessStatus", "Process is not active.");
            if (process.ExpiresOn < App.TimeService.UtcNow)
            {
                process.Status = LoginProcessStatus.Expired;
                session.SaveChanges();
                ctx.ThrowIf(true, ClientFaultCodes.InvalidAction, "Process", "Process expired.");
            }
            ctx.ThrowIf(process.ProcessType != LoginProcessType.PasswordReset, ClientFaultCodes.InvalidValue, "ProcessType", "Invalid login process type.");
            ctx.ThrowIf(process.PendingFactors != ExtraFactorTypes.None, ClientFaultCodes.InvalidAction, "PendingSteps", "The login process has verification steps pending");
            //Ok, we're ready
            var login = process.Login;

            ChangeUserPassword(login, newPassword, oneTimeByAdmin: false); //will log incident and fire event
            login.Flags &= ~LoginFlags.Suspended;                          //clear Suspended flag
            //complete process
            process.Status = LoginProcessStatus.Completed;
            session.SaveChanges();
            //Send notification
            var email = FindLoginFactor(login, ExtraFactorTypes.Email);

            if (email != null)
            {
                SendNotification(session.Context, LoginNotificationTypes.PasswordReset, NotificationMediaTypes.Email, email, login.UserId,
                                 new Dictionary <string, object>()
                {
                    { "UserName", login.UserName }
                });
            }
        }
 //This metod is a default pin generator and is referenced by LoginModuleSettings.PinGenerator
 public static string DefaultGeneratePin(ILoginProcess process, ILoginExtraFactor factor)
 {
     switch(factor.FactorType) {
     case ExtraFactorTypes.Phone:
     case ExtraFactorTypes.Email:
     default:
       return RandomHelper.GenerateRandomString(3, CharKinds.UpperLetter) + RandomHelper.GenerateRandomString(5, CharKinds.Digit);
       }
 }
Esempio n. 9
0
 public static LoginProcess ToModel(this ILoginProcess process)
 {
     if (process == null)
     {
         return(null);
     }
     return(new LoginProcess()
     {
         Token = process.Token, CompletedFactors = process.CompletedFactors, PendingFactors = process.PendingFactors
     });
 }
Esempio n. 10
0
        //TODO: block the IP of the originator of the process after multiple failures, build IncidentTrigger for this
        public void AbortPasswordReset(ILoginProcess process)
        {
            var session = EntityHelper.GetSession(process);

            if (process.Status != LoginProcessStatus.Active)
            {
                return;
            }
            process.Status = LoginProcessStatus.AbortedAsFraud;
            OnLoginEvent(session.Context, LoginEventType.ProcessAborted, process.Login, "Login process aborted");
            session.SaveChanges();
        }
Esempio n. 11
0
        //This metod is a default pin generator and is referenced by LoginModuleSettings.PinGenerator
        public static string DefaultGeneratePin(ILoginProcess process, ILoginExtraFactor factor)
        {
            switch (factor.FactorType)
            {
            case ExtraFactorTypes.Phone:
                return(RandomHelper.GenerateSafeRandomNumber(5));

            case ExtraFactorTypes.Email:
            default:
                return(RandomHelper.GenerateSafeRandomWord(10));
            }
        }
Esempio n. 12
0
 public Task SendMessage(OperationContext context, LoginMessageType messageType,
                         ILoginExtraFactor factor, ILoginProcess process = null)
 {
     if (messageType == LoginMessageType.Pin)
     {
         PinMessages.Add(new PinInfoMessage()
         {
             Pin = process.CurrentPin, Email = process.CurrentFactor.FactorValue
         });
     }
     return(Task.CompletedTask);
 }
Esempio n. 13
0
 //TODO: block the IP of the originator of the process after multiple failures, build IncidentTrigger for this
 public void AbortPasswordReset(ILoginProcess process)
 {
     var session = EntityHelper.GetSession(process);
       if(process.Status != LoginProcessStatus.Active)
     return;
       process.Status = LoginProcessStatus.AbortedAsFraud;
       LogIncident(session.Context, LoginIncidentType, "Aborted:" + process.ProcessType,
     "Process aborted, user: "******"PasswordReset", "Password reset aborted for " + process.Login.UserName, "AbortAsFraud", operationContext: session.Context);
       OnLoginEvent(session.Context, LoginEventType.ProcessAborted, process.Login, "Login process aborted");
       session.SaveChanges();
 }
Esempio n. 14
0
        //TODO: block the IP of the originator of the process after multiple failures, build IncidentTrigger for this
        public void AbortPasswordReset(ILoginProcess process)
        {
            var session = EntityHelper.GetSession(process);

            if (process.Status != LoginProcessStatus.Active)
            {
                return;
            }
            process.Status = LoginProcessStatus.AbortedAsFraud;
            LogIncident(session.Context, LoginIncidentType, "Aborted:" + process.ProcessType,
                        "Process aborted, user: "******"PasswordReset", "Password reset aborted for " + process.Login.UserName, "AbortAsFraud", operationContext: session.Context);
            OnLoginEvent(session.Context, LoginEventType.ProcessAborted, process.Login, "Login process aborted");
            session.SaveChanges();
        }
Esempio n. 15
0
 protected virtual void SendPin(ILoginProcess process, ExtraFactorTypes factorType, string factor, string pin)
 {
     var session = EntityHelper.GetSession(process);
       string mediaType = GetMediaType(factorType);
       Util.CheckNotEmpty(mediaType, "Cannot send pin, unsupported factor type: {0}.", factorType);
       var notificationType = GetPinNotificationType(process.ProcessType);
       var userId = process.Login.UserId;
       var msg = new NotificationMessage() { Type = notificationType, MediaType = mediaType, Recipients = factor, MainRecipientUserId = userId, Culture = session.Context.UserCulture };
       msg.From = _settings.DefaultEmailFrom;
       msg.Parameters[LoginNotificationKeys.BackHitUrlBase] = _settings.BackHitUrlBase;
       msg.Parameters[LoginNotificationKeys.Pin] = pin;
       msg.Parameters[LoginNotificationKeys.ProcessToken] = process.Token;
       msg.Parameters[LoginNotificationKeys.UserName] = process.Login.UserName;
       _notificationService.Send(session.Context, msg);
 }
Esempio n. 16
0
        //submit pin entered by user or from clicked URL
        public bool SubmitPin(ILoginProcess process, string pin)
        {
            var session = EntityHelper.GetSession(process);

            session.Context.ThrowIfEmpty(pin, ClientFaultCodes.InvalidAction, "Pin", "Pin may not be empty.");
            pin = pin.ToUpperInvariant();
            session.Context.ThrowIfEmpty(process.CurrentPin, ClientFaultCodes.InvalidAction, "Pin", "Process.Pin is not expected by the login process.");
            session.Context.ThrowIfNull(process.CurrentFactor, ClientFaultCodes.InvalidAction, "Pin", "Current factor is not set in login process.");
            bool match;

            if (process.CurrentFactor.FactorType == ExtraFactorTypes.GoogleAuthenticator)
            {
                var secret = process.CurrentFactor.FactorValue;
                match = GoogleAuthenticator.GoogleAuthenticatorUtil.CheckPasscode(secret, pin);
            }
            else
            {
                match = process.CurrentPin == pin;
            }
            if (!match)
            {
                process.FailCount++;
                OnLoginEvent(session.Context, LoginEventType.PinMismatch, process.Login);
                var msg = StringHelper.SafeFormat("Invalid pin submitted, user {0}, pin: {1}", process.Login.UserName, pin);
                LogIncident(session.Context, LoginIncidentType, "InvalidPin", msg, process.Login, process.Login.UserName);
                return(false);
            }
            // Pins match; we allow repeated submits of the same pin; we nullify CurrentFactor on first successful submit,
            // but keep CurrentPin for future matches
            if (process.CurrentFactor != null)
            {
                OnLoginEvent(session.Context, LoginEventType.PinMatched, process.Login, "Pin matched, factor verified: " + process.CurrentFactor.FactorType);
                process.PendingFactors   &= ~process.CurrentFactor.FactorType;
                process.CompletedFactors |= process.CurrentFactor.FactorType;
                if (process.ProcessType == LoginProcessType.FactorVerification)
                {
                    process.CurrentFactor.VerifiedOn = App.TimeService.UtcNow;
                    process.Status = LoginProcessStatus.Completed;
                }
                process.CurrentFactor = null; //nullify factor but keep pin
            }
            session.SaveChanges();
            if (process.ProcessType == LoginProcessType.FactorVerification)
            {
                CheckLoginFactorsSetupCompleted(process.Login);
            }
            return(true);
        }
Esempio n. 17
0
        protected virtual void SendPin(ILoginProcess process, ExtraFactorTypes factorType, string factor, string pin)
        {
            var    session   = EntityHelper.GetSession(process);
            string mediaType = GetMediaType(factorType);

            Util.CheckNotEmpty(mediaType, "Cannot send pin, unsupported factor type: {0}.", factorType);
            var notificationType = GetPinNotificationType(process.ProcessType);
            var userId           = process.Login.UserId;
            var msg = new NotificationMessage()
            {
                Type = notificationType, MediaType = mediaType, Recipients = factor, MainRecipientUserId = userId, Culture = session.Context.UserCulture
            };

            msg.From = _settings.DefaultEmailFrom;
            msg.Parameters[LoginNotificationKeys.BackHitUrlBase] = _settings.BackHitUrlBase;
            msg.Parameters[LoginNotificationKeys.Pin]            = pin;
            msg.Parameters[LoginNotificationKeys.ProcessToken]   = process.Token;
            msg.Parameters[LoginNotificationKeys.UserName]       = process.Login.UserName;
            _notificationService.Send(session.Context, msg);
        }
Esempio n. 18
0
 public bool CheckSecretQuestionAnswer(ILoginProcess process, ISecretQuestion question, string userAnswer)
 {
     var session = EntityHelper.GetSession(process);
       var qa = process.Login.SecretQuestionAnswers.FirstOrDefault(a => a.Question == question);
       session.Context.ThrowIfNull(qa, ClientFaultCodes.InvalidValue, "question",
     "The question is not registered as user question. Question: {0}", question.Question);
       var match = CheckUserAnswer(qa, userAnswer);
       if(!match) {
     process.FailCount++;
     session.SaveChanges();
     OnLoginEvent(session.Context, LoginEventType.QuestionAnswersFailed, process.Login, "Secret questions check failed.");
     var msg = StringHelper.SafeFormat("Invalid answer to secret question '{0}';  user {1}.", question.Question, process.Login.UserName);
     LogIncident(session.Context, LoginIncidentType, "InvalidQuestionAnswer", msg, process.Login, process.Login.UserName);
     return false;
       }
       // Add question number to list of answered questions in process record.
       // If all questions are answered, clear Pending step CheckQuestionAnswers
       var strAllAnswered = process.AnsweredQuestions ?? string.Empty;
       var answeredNumbers = strAllAnswered.Split(',').Select(sn => sn.Trim()).ToList();
       var newAnsNum = qa.Number.ToString();
       if(!answeredNumbers.Contains(newAnsNum)) {
     answeredNumbers.Add(newAnsNum);
     process.AnsweredQuestions = string.Join(",", answeredNumbers);
     if(answeredNumbers.Count == process.Login.SecretQuestionAnswers.Count) {
       //Set questions as answers
       process.PendingFactors &= ~ExtraFactorTypes.SecretQuestions;
     }
     session.SaveChanges();
       }
       return true;
 }
Esempio n. 19
0
 //submit pin entered by user or from clicked URL
 public bool SubmitPin(ILoginProcess process, string pin)
 {
     var session = EntityHelper.GetSession(process);
       session.Context.ThrowIfEmpty(pin, ClientFaultCodes.InvalidAction, "Pin", "Pin may not be empty.");
       pin = pin.ToUpperInvariant();
       session.Context.ThrowIfEmpty(process.CurrentPin, ClientFaultCodes.InvalidAction, "Pin", "Process.Pin is not expected by the login process.");
       session.Context.ThrowIfNull(process.CurrentFactor, ClientFaultCodes.InvalidAction, "Pin", "Current factor is not set in login process.");
       bool match;
       if (process.CurrentFactor.FactorType == ExtraFactorTypes.GoogleAuthenticator) {
     var secret = process.CurrentFactor.Info.DecryptString(_settings.EncryptionChannelName);
     match = GoogleAuthenticator.GoogleAuthenticatorUtil.CheckPasscode(secret, pin);
       } else {
     match = process.CurrentPin == pin;
       }
       if(!match) {
     process.FailCount++;
     OnLoginEvent(session.Context, LoginEventType.PinMismatch, process.Login);
     var msg = StringHelper.SafeFormat("Invalid pin submitted, user {0}, pin: {1}", process.Login.UserName, pin);
     LogIncident(session.Context, LoginIncidentType, "InvalidPin", msg, process.Login, process.Login.UserName);
     return false;
       }
       // Pins match; we allow repeated submits of the same pin; we nullify CurrentFactor on first successful submit,
       // but keep CurrentPin for future matches
       if(process.CurrentFactor != null) {
     OnLoginEvent(session.Context, LoginEventType.PinMatched, process.Login, "Pin matched, factor verified: " + process.CurrentFactor.FactorType);
     process.PendingFactors &= ~process.CurrentFactor.FactorType;
     process.CompletedFactors |= process.CurrentFactor.FactorType;
     if(process.ProcessType == LoginProcessType.FactorVerification) {
       process.CurrentFactor.VerifiedOn = App.TimeService.UtcNow;
       process.Status = LoginProcessStatus.Completed;
     }
     process.CurrentFactor = null; //nullify factor but keep pin
       }
       session.SaveChanges();
       if(process.ProcessType == LoginProcessType.FactorVerification)
     CheckLoginFactorsSetupCompleted(process.Login);
       return true;
 }
Esempio n. 20
0
 public string GeneratePin(ILoginProcess process, ILoginExtraFactor factor)
 {
     return(_settings.PinGenerator(process, factor));
 }
Esempio n. 21
0
 public void SendPin(ILoginProcess process, ILoginExtraFactor factor, string factorValue = null, string pin = null)
 {
     Util.Check(process.Login == factor.Login, "LoginProcess tries to use login factor not assigned to process's login.");
       var session = EntityHelper.GetSession(process);
       var activeAlready = GetActiveConfirmationProcesses(factor, LoginProcessType.FactorVerification);
       session.Context.ThrowIf(activeAlready.Count > 2, ClientFaultCodes.InvalidAction, "Factor",
     "Cannot send pin - several pins already sent and are waiting for confirmation.");
       process.CurrentFactor = factor;
       if (factor.FactorType == ExtraFactorTypes.GoogleAuthenticator) {
     //do not generate or send pin
       } else {
     pin = pin ?? _settings.PinGenerator(process, factor);
     if (string.IsNullOrWhiteSpace(factorValue))
       factorValue = factor.Info.DecryptString(_settings.EncryptionChannelName);
     process.CurrentPin = pin;
     SendPin(process, factor.FactorType, factorValue, pin);
       }
       session.SaveChanges();
       var logMsg = StringHelper.SafeFormat("Pin sent to user {0} using factor '{1}'. ", factor.Login.UserName, factorValue);
       OnLoginEvent(session.Context, LoginEventType.PinSent, factor.Login, logMsg);
 }
Esempio n. 22
0
 public void ResetPassword(ILoginProcess process, string newPassword)
 {
     var session = EntityHelper.GetSession(process);
       var ctx = session.Context;
       ctx.ThrowIf(process.Status != LoginProcessStatus.Active, ClientFaultCodes.InvalidAction, "ProcessStatus", "Process is not active.");
       if(process.ExpiresOn < App.TimeService.UtcNow) {
     process.Status = LoginProcessStatus.Expired;
     session.SaveChanges();
     ctx.ThrowIf(true, ClientFaultCodes.InvalidAction, "Process", "Process expired.");
       }
       ctx.ThrowIf(process.ProcessType != LoginProcessType.PasswordReset, ClientFaultCodes.InvalidValue, "ProcessType", "Invalid login process type.");
       ctx.ThrowIf(process.PendingFactors != ExtraFactorTypes.None, ClientFaultCodes.InvalidAction, "PendingSteps", "The login process has verification steps pending");
       //Ok, we're ready
       var login = process.Login;
       ChangeUserPassword(login, newPassword, oneTimeByAdmin: false); //will log incident and fire event
       login.Flags &= ~LoginFlags.Suspended; //clear Suspended flag
       //complete process
       process.Status = LoginProcessStatus.Completed;
       session.SaveChanges();
       //Send notification
       var email = FindLoginFactor(login, ExtraFactorTypes.Email);
       if(email != null)
     SendNotification(session.Context, LoginNotificationTypes.PasswordReset, NotificationMediaTypes.Email, email, login.UserId,
       new Dictionary<string, object>() { { "UserName", login.UserName }});
 }
Esempio n. 23
0
 public string GeneratePin(ILoginProcess process, ILoginExtraFactor factor)
 {
     return _settings.PinGenerator(process, factor);
 }