Ejemplo n.º 1
0
        public async Task <TwoFactorResponseModel> PutTwoFactorRegenerate([FromBody] RegenerateTwoFactorRequestModel model)
        {
            var user = await _userService.GetUserByPrincipalAsync(User);

            if (!await _userManager.CheckPasswordAsync(user, model.MasterPasswordHash))
            {
                await Task.Delay(2000);

                throw new BadRequestException("MasterPasswordHash", "Invalid password.");
            }

            if (!await _userManager.VerifyTwoFactorTokenAsync(user, TwoFactorProviderType.Authenticator.ToString(), model.Token))
            {
                await Task.Delay(2000);

                throw new BadRequestException("Token", "Invalid token.");
            }

            if (user.TwoFactorEnabled)
            {
                user.TwoFactorRecoveryCode = Guid.NewGuid().ToString("N");
                await _userService.SaveUserAsync(user);
            }

            var response = new TwoFactorResponseModel(user);

            return(response);
        }
Ejemplo n.º 2
0
        public async Task <TwoFactorResponseModel> PutTwoFactor([FromBody] UpdateTwoFactorRequestModel model)
        {
            var user = _currentContext.User;

            if (!await _userManager.CheckPasswordAsync(user, model.MasterPasswordHash))
            {
                await Task.Delay(2000);

                throw new BadRequestException("MasterPasswordHash", "Invalid password.");
            }

            if (model.Enabled.Value && !await _userManager.VerifyTwoFactorTokenAsync(user, "Authenticator", model.Token))
            {
                await Task.Delay(2000);

                throw new BadRequestException("Token", "Invalid token.");
            }

            user.TwoFactorProvider = TwoFactorProvider.Authenticator;
            user.TwoFactorEnabled  = model.Enabled.Value;
            await _userService.SaveUserAsync(user);

            var response = new TwoFactorResponseModel(user);

            return(response);
        }
Ejemplo n.º 3
0
        public async Task <TwoFactorResponseModel> GetTwoFactor(string masterPasswordHash, TwoFactorProviderType provider)
        {
            var user = await _userService.GetUserByPrincipalAsync(User);

            if (!await _userManager.CheckPasswordAsync(user, masterPasswordHash))
            {
                await Task.Delay(2000);

                throw new BadRequestException("MasterPasswordHash", "Invalid password.");
            }

            await _userService.GetTwoFactorAsync(user, provider);

            var response = new TwoFactorResponseModel(user);

            return(response);
        }
Ejemplo n.º 4
0
        public async Task <TwoFactorResponseModel> ValidateTwoFactorCodeAsync(string code)
        {
            // Initially setting this to Fail
            var response = new TwoFactorResponseModel
            {
                Code            = string.Empty,
                Email           = string.Empty,
                IsValid         = false,
                RememberDevice  = false,
                ResponseMessage = new ResponseStatusInfoModel
                {
                    Message    = "Code-InValid",
                    StatusCode = HttpStatusCode.Unauthorized
                }
            };

            try
            {
                string twoFactorToken = _httpContextAccessor.HttpContext.Request.Headers["twoFactorToken"];

                var loggedInUserId = GetLoggedInUserId();
                var user           = await _userManager.FindByIdAsync(loggedInUserId);

                if (user != null && twoFactorToken != null && !string.IsNullOrEmpty(code))
                {
                    var userResult = await _db.TwoFactorCodes.Where(x =>
                                                                    x.UserId == user.Id &&
                                                                    x.CodeExpired == false &&
                                                                    x.ExpiryDate > DateTime.UtcNow &&
                                                                    !x.CodeIsUsed && x.Attempts <= 3).FirstOrDefaultAsync();

                    if (userResult != null)
                    {
                        // Check Code attempts
                        if (userResult.TwoFactorCode != code)
                        {
                            userResult.Attempts -= 1;
                            _db.Update(userResult);
                            await _db.SaveChangesAsync();

                            response.Attempts = userResult.Attempts;
                            _cookieSvc.SetCookie("user_id", EncryptData <string>(loggedInUserId, _dataProtectionKeys.ApplicationUserKey), Convert.ToInt32(userResult.ExpiryDate.Subtract(DateTime.UtcNow).TotalMinutes));
                            if (userResult.Attempts == 0)
                            {
                                await using var dbContextTransaction = await _db.Database.BeginTransactionAsync();

                                user.LockoutEnabled   = true;
                                _db.Entry(user).State = EntityState.Modified;
                                await _db.SaveChangesAsync();

                                await dbContextTransaction.CommitAsync();
                            }

                            return(response);
                        }

                        var decryptedTwoFactorToken = DecryptData(twoFactorToken, userResult.EncryptionKey2Fa);

                        if (decryptedTwoFactorToken == userResult.Token)
                        {
                            // Before sending true we need to set the code as Expired
                            // reset the two-factor again
                            userResult.CodeExpired   = true;
                            userResult.CodeIsUsed    = true;
                            response.Code            = userResult.TwoFactorCode;
                            response.Email           = user.Email;
                            response.IsValid         = true;
                            response.RememberDevice  = false;
                            response.ResponseMessage = new ResponseStatusInfoModel
                            {
                                Message    = "Code-Valid",
                                StatusCode = HttpStatusCode.OK
                            };
                            return(response);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error("An error occurred at ValidateTwoFactorAsync {Error} {StackTrace} {InnerException} {Source}",
                          ex.Message, ex.StackTrace, ex.InnerException, ex.Source);
            }

            return(response);
        }
Ejemplo n.º 5
0
        public async Task <TwoFactorResponseModel> SendTwoFactorAsync(TwoFactorRequestModel model)
        {
            var twoFactorResponse = new TwoFactorResponseModel();
            var result            = new TwoFactorCodeModel();

            try
            {
                var protectorProvider = _provider.GetService <IDataProtectionProvider>();

                var userIdFromHeader = _httpContextAccessor.HttpContext.Request.Headers["user_id"];
                var twoFactorToken   = model.TwoFactorToken;

                // If two factor token is null we dont want to further execute this method
                if (!string.IsNullOrEmpty(twoFactorToken) && !string.IsNullOrEmpty(userIdFromHeader))
                {
                    var userId = DecryptData(userIdFromHeader, _dataProtectionKeys.ApplicationUserKey).ToString();
                    // First find user with that Id id two-factor Table
                    // If user was found, check if the token is valid or expired
                    var userResult = await _db.TwoFactorCodes.Where(x =>
                                                                    x.UserId == userId &&
                                                                    x.CodeExpired == false &&
                                                                    x.CodeIsUsed == false &&
                                                                    x.ExpiryDate > DateTime.UtcNow).FirstOrDefaultAsync();

                    if (userResult != null)
                    {
                        // Decrypted Two-Factor-Token from request
                        var protector = protectorProvider.CreateProtector(userResult.EncryptionKey2Fa);
                        var decryptedTwoFactorToken = protector.Unprotect(twoFactorToken);

                        // Get the Application User
                        var appUser = await _userManager.FindByIdAsync(userId);

                        // If both the values match request vs DB
                        if (userResult.Token != null && decryptedTwoFactorToken != null && userResult.Token == decryptedTwoFactorToken)
                        {
                            // check in current request if they want to remember
                            userResult.RememberDevice            = model.RememberDevice;
                            await using var dbContextTransaction = await _db.Database.BeginTransactionAsync();

                            _db.Entry(userResult).State = EntityState.Modified;
                            await _db.SaveChangesAsync();

                            await dbContextTransaction.CommitAsync();

                            twoFactorResponse.IsValid         = true;
                            twoFactorResponse.Email           = appUser.Email;
                            twoFactorResponse.Code            = userResult.TwoFactorCode;
                            twoFactorResponse.RememberDevice  = userResult.RememberDevice;
                            twoFactorResponse.ResponseMessage = new ResponseStatusInfoModel
                            {
                                Message    = "Authentication Success",
                                StatusCode = HttpStatusCode.OK
                            };
                            protector = protectorProvider.CreateProtector(_dataProtectionKeys.ApplicationUserKey);
                            var protectedUserId = protector.Protect(userId);
                            _cookieSvc.SetCookie("user_id", protectedUserId, Convert.ToInt32(userResult.ExpiryDate.Subtract(DateTime.UtcNow).TotalMinutes));
                            return(twoFactorResponse);
                        }
                    }
                }
                twoFactorResponse.IsValid         = false;
                twoFactorResponse.Email           = string.Empty;
                twoFactorResponse.Code            = string.Empty;
                twoFactorResponse.RememberDevice  = false;
                twoFactorResponse.ResponseMessage = new ResponseStatusInfoModel
                {
                    Message    = "Authentication Failed",
                    StatusCode = HttpStatusCode.Unauthorized
                };
            }
            catch (Exception ex)
            {
                Log.Error("An error occurred at ValidateTwoFactorAsync {Error} {StackTrace} {InnerException} {Source}",
                          ex.Message, ex.StackTrace, ex.InnerException, ex.Source);
            }

            return(twoFactorResponse);
        }