public async Task Alias_IndexPatchMatchingOld_NoContentWithChangedPassword()
        {
            using (IdentityWsDbContext ef = CreateEf()) {
                Being being = new Being
                {
                    SaltedHashedPassword = Sha512Util.SaltAndHashNewPassword("password1")
                };
                ef.Aliases.Add(new Alias
                {
                    EmailAddress = "*****@*****.**",
                    Being        = being
                });
                await ef.SaveChangesAsync();

                AliasesController patient = new AliasesController(ef, dummyLog, now, dummyRunner);

                AliasesController.IndexPatchRequestBody body = new AliasesController.IndexPatchRequestBody
                {
                    oldPassword = "******",
                    password    = "******"
                };
                IActionResult result = await patient.IndexPatch("*****@*****.**", body);

                result.Should().BeOfType <NoContentResult>($"'{nameof(body.oldPassword)}' matched");
                Sha512Util.TestPassword("p@ssword1", being.SaltedHashedPassword).Should().BeTrue("the password should have been changed");
            }
        }
Ejemplo n.º 2
0
        public async Task <IActionResult> Login([EmailAddress, MaxLength(100)] string email_address, [Required, MaxLength(20)] string client,
                                                [FromBody] LoginRequestBody body)
        {
            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            // Get the entities.
            Alias alias = await ef.Aliases
                          .Include(a => a.Being).ThenInclude(b => b.Clients)
                          .FirstOrDefaultAsync(a => a.EmailAddress == email_address);

            Being being = alias?.Being;

            if (being == null || !being.Clients.Any(c => c.ClientName == client))
            {
                return(NotFound());
            }

            // Check the number of consecutive failures.
            DateTime period_start         = now.UtcNow.AddMinutes(-1 * config.GetValue <double>("LockoutPeriodMins"));
            int      consecutive_failures = await ef.LoginAttempts
                                            .Where(a => a.Alias.BeingID == being.BeingID &&
                                                   a.DateCreated >= period_start &&
                                                   !a.Success &&
                                                   !ef.LoginAttempts.Any(a2 => a2.Alias.BeingID == being.BeingID &&
                                                                         a2.LoginAttemptID > a.LoginAttemptID &&
                                                                         a2.Success))
                                            .CountAsync();

            if (consecutive_failures >= config.GetValue <int>("MaxFailedLoginsBeforeLockout"))
            {
                return(StatusCode(StatusCodes.Status503ServiceUnavailable));
            }

            // Check the password.
            bool password_ok = Sha512Util.TestPassword(body.password, being.SaltedHashedPassword);

            // Log the attempt.
            ef.LoginAttempts.Add(new LoginAttempt
            {
                AliasID    = alias.AliasID,
                Success    = password_ok,
                ClientName = client
            });
            await ef.SaveChangesAsync();

            return(password_ok ? (IActionResult)NoContent() : Unauthorized());
        }
Ejemplo n.º 3
0
        public async Task <IActionResult> IndexPatch([EmailAddress, MaxLength(100)] string email_address,
                                                     [FromBody] IndexPatchRequestBody body)
        {
            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            // Get the being.
            Being being = (await ef.Aliases
                           .Include(a => a.Being)
                           .FirstOrDefaultAsync(a => a.EmailAddress == email_address))
                          ?.Being;

            if (being == null)
            {
                return(NotFound());
            }

            if (body.resetToken != null)
            {
                // Authenticate via reset token.
                if (body.oldPassword != null)
                {
                    // Only one of resetToken or oldPassword may be supplied.
                    return(BadRequest());
                }
                if (!being.PasswordResetTokenValidUntil.HasValue || being.PasswordResetTokenValidUntil <= now.UtcNow ||
                    being.PasswordResetToken != body.resetToken)
                {
                    return(Unauthorized());
                }
                if (Sha512Util.TestPassword(body.password, being.SaltedHashedPassword))
                {
                    // Cannot change password to itself.
                    return(StatusCode(StatusCodes.Status409Conflict));
                }
                // The token is used up.
                being.PasswordResetToken           = null;
                being.PasswordResetTokenValidUntil = null;
            }
            else
            {
                // Authenticate via old password.
                if (body.oldPassword == null)
                {
                    // One of resetToken or oldPassword must be supplied.
                    return(BadRequest());
                }
                if (!Sha512Util.TestPassword(body.oldPassword, being.SaltedHashedPassword))
                {
                    return(Unauthorized());
                }
                if (body.oldPassword == body.password)
                {
                    // Cannot change password to itself.
                    return(StatusCode(StatusCodes.Status409Conflict));
                }
            }

            // Change the password.
            being.SaltedHashedPassword = Sha512Util.SaltAndHashNewPassword(body.password);
            await ef.SaveChangesAsync();

            return(NoContent());
        }
Ejemplo n.º 4
0
 public void MismatchingPasswordAndHash_TestPassword_ReturnsFalse()
 {
     Sha512Util.TestPassword("Hello worldx!", "$6$saltstring$svn8UoSVapNtMuq1ukKS4tPQd8iKwSMHWjl/O817G3uBnIFNjnQJuesI68u4OTLiBFdcbYEdFCoEOfaS35inz1")
     .Should().BeFalse("the hash does not match the password");
 }