Exemplo n.º 1
0
        public async Task ThenItShouldReturnUserWhenCredentialsMatch()
        {
            // Act
            var actual = await _commandHandler.Handle(_command);

            // Assert
            Assert.AreSame(_user, actual);
        }
        public async Task Handle_GivenValidUser_ShouldGenerateUserToken()
        {
            // Arrange
            var authCommand = new AuthenticateUserCommand
            {
                MerchantID = "HB123H7123G712",
                ApiKey     = "314179fa-7de9-4c9d-8d52-fb6f62ab3815"
            };

            // Act
            var result = await _sut.Handle(authCommand, CancellationToken.None);

            // Assert
            result.Should().NotBeNull();
        }
Exemplo n.º 3
0
        public async Task Handle_GivenSavingSucceeds_ExpectSuccessfulResult()
        {
            var user = new Mock <IUser>();

            user.Setup(x => x.PasswordHash).Returns(BCrypt.Net.BCrypt.HashPassword("password"));
            user.Setup(x => x.Profile).Returns(new Profile(TestVariables.UserId, "first-name", "last-name"));
            user.Setup(x => x.AuthenticatorApps).Returns(new List <AuthenticatorApp>());
            user.Setup(x => x.AuthenticatorDevices).Returns(new List <AuthenticatorDevice>());
            user.Setup(x => x.IsVerified).Returns(true);

            var userRepository = new Mock <IUserRepository>();
            var unitOfWork     = new Mock <IUnitOfWork>();

            unitOfWork.Setup(x => x.SaveEntitiesAsync(It.IsAny <CancellationToken>())).ReturnsAsync(() => true);
            userRepository.Setup(x => x.UnitOfWork).Returns(unitOfWork.Object);
            userRepository.Setup(x => x.FindByEmailAddress(It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(() => Maybe.From(user.Object));

            var clock = new Mock <IClock>();

            var securitySettings = new Mock <IOptions <SecuritySettings> >();

            securitySettings.Setup(x => x.Value).Returns(new SecuritySettings());

            var fido = new Mock <IFido2>();

            var handler = new AuthenticateUserCommandHandler(userRepository.Object, clock.Object, securitySettings.Object, fido.Object);
            var cmd     = new AuthenticateUserCommand("email-address", "password");
            var result  = await handler.Handle(cmd, CancellationToken.None);

            Assert.True(result.IsSuccess);
        }
Exemplo n.º 4
0
        public async Task Handle_GivenUserDoesExistButPasswordDoesNotVerifyAndAccountsAreLockableAndAttemptsNotLess_ExpectFailedResultAndUnsuccessfulAttemptLoggedWithLockApplied()
        {
            var user = new Mock <IUser>();

            user.Setup(x => x.PasswordHash).Returns(BCrypt.Net.BCrypt.HashPassword("password"));
            user.Setup(x => x.IsVerified).Returns(true);

            var userRepository = new Mock <IUserRepository>();
            var unitOfWork     = new Mock <IUnitOfWork>();

            unitOfWork.Setup(x => x.SaveEntitiesAsync(It.IsAny <CancellationToken>())).ReturnsAsync(() => true);
            userRepository.Setup(x => x.UnitOfWork).Returns(unitOfWork.Object);
            userRepository.Setup(x => x.FindByEmailAddress(It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(() => Maybe.From(user.Object));

            var clock = new Mock <IClock>();

            var securitySettings = new Mock <IOptions <SecuritySettings> >();

            securitySettings.Setup(x => x.Value).Returns(() => new SecuritySettings {
                AllowedAttempts = 0
            });

            var fido = new Mock <IFido2>();

            var handler = new AuthenticateUserCommandHandler(userRepository.Object, clock.Object, securitySettings.Object, fido.Object);
            var cmd     = new AuthenticateUserCommand("email-address", "wrong-password");
            var result  = await handler.Handle(cmd, CancellationToken.None);

            Assert.True(result.IsFailure);
            Assert.Equal(ErrorCodes.AuthenticationFailed, result.Error.Code);
            user.Verify(x => x.ProcessUnsuccessfulAuthenticationAttempt(It.IsAny <DateTime>(), true));
        }
Exemplo n.º 5
0
        public void AuthenticateCommand_PresentWrongPassword_ThrowsException()
        {
            // ---- Arrange ----

            const string email         = "*****@*****.**";
            const string name          = "Test user";
            const string wrongPassword = "******";
            const string password      = "******";
            var          passwordHash  = AuthUtils.GetMd5Hash(password);

            var testUser = new UserIdentityModel(
                Guid.NewGuid(),
                email,
                "Test user",
                name,
                passwordHash,
                Instant.MinValue);

            _authRepositoryMock.Setup(r => r.GetUserIdentity(email))
            .ReturnsAsync(() => testUser);

            var command = new AuthenticateUserCommand(email, wrongPassword);
            var handler = new AuthenticateUserCommandHandler(_repositoryProviderMock.Object, _configuration);

            // ---- Act & Assert ----

            Assert.ThrowsAsync <WrongPasswordException>(
                async() => await handler.Handle(command, CancellationToken.None));

            _authRepositoryMock.Verify(r => r.GetUserIdentity(email), Times.Once);
        }
Exemplo n.º 6
0
        public async Task Handle_GivenUserDoesExistAndPasswordDoesVerifyAndHasDeviceSetUp_ExpectSuccessfulResultWithAwaitingMfaDeviceAndAPartialAttemptLogged()
        {
            var user   = new Mock <IUser>();
            var userId = Guid.NewGuid();

            user.Setup(x => x.Id).Returns(userId);
            user.Setup(x => x.EmailAddress).Returns("email-address");
            user.Setup(x => x.PasswordHash).Returns(BCrypt.Net.BCrypt.HashPassword("password"));
            user.Setup(x => x.AuthenticatorApps).Returns(new List <AuthenticatorApp>());
            user.Setup(x => x.AuthenticatorDevices).Returns(new List <AuthenticatorDevice>
            {
                new AuthenticatorDevice(
                    TestVariables.AuthenticatorDeviceId,
                    TestVariables.Now,
                    TestVariables.AuthenticatorDevicePublicKey,
                    TestVariables.AuthenticatorDeviceCredentialId,
                    TestVariables.AuthenticatorDeviceAaguid,
                    1,
                    "name",
                    "cred-type"),
            });
            user.Setup(x => x.IsVerified).Returns(true);

            var userRepository = new Mock <IUserRepository>();
            var unitOfWork     = new Mock <IUnitOfWork>();

            unitOfWork.Setup(x => x.SaveEntitiesAsync(It.IsAny <CancellationToken>())).ReturnsAsync(() => true);
            userRepository.Setup(x => x.UnitOfWork).Returns(unitOfWork.Object);
            userRepository.Setup(x => x.FindByEmailAddress(It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(() => Maybe.From(user.Object));

            var clock = new Mock <IClock>();

            var securitySettings = new Mock <IOptions <SecuritySettings> >();

            securitySettings.Setup(x => x.Value).Returns(new SecuritySettings());

            var fido = new Mock <IFido2>();

            fido.Setup(
                x => x.GetAssertionOptions(
                    It.IsAny <IEnumerable <PublicKeyCredentialDescriptor> >(),
                    It.IsAny <UserVerificationRequirement>(), It.IsAny <AuthenticationExtensionsClientInputs>()))
            .Returns(new AssertionOptions());

            var handler = new AuthenticateUserCommandHandler(userRepository.Object, clock.Object, securitySettings.Object, fido.Object);
            var cmd     = new AuthenticateUserCommand("email-address", "password");
            var result  = await handler.Handle(cmd, CancellationToken.None);

            Assert.True(result.IsSuccess);
            Assert.Equal(userId, result.Value.UserId);
            Assert.True(result.Value.SetupMfaProviders.HasFlag(MfaProvider.Device));
            Assert.True(result.Value.SetupMfaProviders.HasFlag(MfaProvider.Email));
            Assert.Equal(BaseAuthenticationProcessCommandResult.AuthenticationState.AwaitingMfaDeviceCode, result.Value.AuthenticationStatus);
            user.Verify(x => x.ProcessPartialSuccessfulAuthenticationAttempt(It.IsAny <DateTime>(), AuthenticationHistoryType.DeviceMfaRequested));
        }
        public async Task ShouldFailAuthenticationIfWrongPassword()
        {
            var dbContext  = InfrastructureFactory.GetInMemoryContext(nameof(ShouldFailAuthenticationIfWrongPassword));
            var unitOfWork = InfrastructureFactory.GetEfUnitOfWork(dbContext);
            var user       = EntityFactory.GetUser("johndoe", "Pass@123");
            await unitOfWork.AddAndSaveAsync(user);

            var handler = new AuthenticateUserCommandHandler(unitOfWork, InfrastructureFactory.GetSha1Hasher(), InfrastructureFactory.GetMachineDateTime());

            Assert.ThrowsAsync <UserAuthenticationFailedException>(() => handler.Handle(new AuthenticateUserCommand("johndoe", "Pass@13", UserAuthConstants.TokenExpirationTime), default));
        }
Exemplo n.º 8
0
        public void AuthenticateCommand_AuthUser_SuccessAuth()
        {
            // ---- Arrange ----

            const string email        = "*****@*****.**";
            const string name         = "Test user";
            const string password     = "******";
            var          passwordHash = AuthUtils.GetMd5Hash(password);

            var clock    = new FakeClock(SystemClock.Instance.GetCurrentInstant());
            var testUser = new UserIdentityModel(
                Guid.NewGuid(),
                email,
                name,
                "user",
                passwordHash,
                clock.GetCurrentInstant());

            _authRepositoryMock.Setup(r => r.GetUserIdentity(email))
            .ReturnsAsync(() => testUser);

            var command = new AuthenticateUserCommand(email, password);
            var handler = new AuthenticateUserCommandHandler(_repositoryProviderMock.Object, _configuration)
            {
                Clock = clock
            };

            AuthAccessModel result = null;

            var lifetime = DurationUtils.FromString(
                _configuration[$"{AuthUtils.Jwt.ConfigKeys.Section}:{AuthUtils.Jwt.ConfigKeys.LifetimeKey}"]);

            // ---- Act ----

            Assert.DoesNotThrowAsync(async() => {
                result = await handler.Handle(command, CancellationToken.None);
            });

            clock.Advance(lifetime); // for check expires token instant

            // ---- Assert ----

            Assert.IsNotNull(result);
            Assert.AreEqual(testUser.Id, result.Id);
            Assert.AreEqual(testUser.Email, result.Email);
            Assert.AreEqual(clock.GetCurrentInstant(), result.ExpiresAt);
            Assert.AreEqual(clock.GetCurrentInstant(), result.ExpiresAt);
            Assert.AreEqual("user", testUser.Role);
            Assert.IsNotEmpty(result.Token);

            _authRepositoryMock.Verify(r => r.GetUserIdentity(email), Times.Once);
        }
        public async Task ShouldReturnAuthenticatedUser()
        {
            var dbContext  = InfrastructureFactory.GetInMemoryContext(nameof(ShouldReturnAuthenticatedUser));
            var unitOfWork = InfrastructureFactory.GetEfUnitOfWork(dbContext);
            var user       = EntityFactory.GetUser("johndoe", "Pass@123");
            await unitOfWork.AddAndSaveAsync(user);

            var handler        = new AuthenticateUserCommandHandler(unitOfWork, InfrastructureFactory.GetSha1Hasher(), InfrastructureFactory.GetMachineDateTime());
            var authentication = await handler.Handle(new AuthenticateUserCommand("johndoe", "Pass@123", UserAuthConstants.TokenExpirationTime), default);

            Assert.AreEqual("johndoe", authentication.User.Nickname);
            Assert.IsFalse(string.IsNullOrEmpty(authentication.Token));
        }
        public void Then_If_Error_A_HttpContextException_Is_Thrown(
            PostAuthenticateUserResult apiResponse,
            AuthenticateUserCommand command,
            [Frozen] Mock <IApimDeveloperApiClient <ApimDeveloperApiConfiguration> > apimDeveloperApiClient,
            AuthenticateUserCommandHandler handler)
        {
            apimDeveloperApiClient.Setup(x =>
                                         x.PostWithResponseCode <PostAuthenticateUserResult>(It.Is <PostAuthenticateUserRequest>(c =>
                                                                                                                                 ((PostAuthenticateUserRequestData)c.Data).Email.Equals(command.Email) &&
                                                                                                                                 ((PostAuthenticateUserRequestData)c.Data).Password.Equals(command.Password))))
            .ReturnsAsync(new ApiResponse <PostAuthenticateUserResult>(apiResponse, HttpStatusCode.BadRequest, "An Error"));

            Assert.ThrowsAsync <HttpRequestContentException>(() => handler.Handle(command, CancellationToken.None));
        }
        public async Task ShouldCreateTokenOnSucesfulAuth()
        {
            var dbContext  = InfrastructureFactory.GetInMemoryContext(nameof(ShouldChangePasswordSaltAndReHashPasswordOnSuccesfulAuth));
            var unitOfWork = InfrastructureFactory.GetEfUnitOfWork(dbContext);
            var user       = EntityFactory.GetUser("johndoe", "Pass@123");
            await unitOfWork.AddAndSaveAsync(user);

            var handler        = new AuthenticateUserCommandHandler(unitOfWork, InfrastructureFactory.GetSha1Hasher(), InfrastructureFactory.GetMachineDateTime());
            var authentication = await handler.Handle(new AuthenticateUserCommand("johndoe", "Pass@123", UserAuthConstants.TokenExpirationTime), default);

            var tokenCount = await dbContext.UserTokens.CountAsync(u => u.Nickname == "johndoe");

            Assert.AreEqual(1, tokenCount);
        }
Exemplo n.º 12
0
        public async Task WhenUserCredentialsAreWrong_ThenUnauthorizedExceptionIsThrown()
        {
            //Arrange
            var users = new List <User>()
            {
                new User()
                {
                    Username = "******", Password = "******"
                }
            };

            dbContextMock.Setup(x => x.Users).Returns(users.ToDbSet());

            //Act
            var command = new AuthenticateUserCommand()
            {
                Username = "******", Password = "******"
            };
            var exception = await Assert.ThrowsAsync <AppException>(() => authenticateUserCommandHandler.Handle(command, new CancellationToken()));

            //Assert
            Assert.Equal(HttpStatusCode.Unauthorized, exception.StatusCode);
            Assert.Equal(Constants.ErrorCodes.InvalidCredentials, exception.Message);
        }
        public async Task Then_The_Query_Is_Handled_And_User_Returned(
            PostAuthenticateUserResult apiResponse,
            AuthenticateUserCommand command,
            [Frozen] Mock <IApimDeveloperApiClient <ApimDeveloperApiConfiguration> > apimDeveloperApiClient,
            AuthenticateUserCommandHandler handler)
        {
            apimDeveloperApiClient.Setup(x =>
                                         x.PostWithResponseCode <PostAuthenticateUserResult>(It.Is <PostAuthenticateUserRequest>(c =>
                                                                                                                                 ((PostAuthenticateUserRequestData)c.Data).Email.Equals(command.Email) &&
                                                                                                                                 ((PostAuthenticateUserRequestData)c.Data).Password.Equals(command.Password))))
            .ReturnsAsync(new ApiResponse <PostAuthenticateUserResult>(apiResponse, HttpStatusCode.OK, ""));

            var actual = await handler.Handle(command, CancellationToken.None);

            actual.User.Should().BeEquivalentTo(apiResponse);
        }
Exemplo n.º 14
0
        public void AuthenticateCommand_PresentInvalidEmail_ThrowsException()
        {
            // ---- Arrange ----

            const string invalidEmail = "invalid_email";
            const string password     = "******";
            var          command      = new AuthenticateUserCommand(invalidEmail, password);
            var          handler      = new AuthenticateUserCommandHandler(_repositoryProviderMock.Object, _configuration);

            // ---- Act & Assert ----

            var exception = Assert.ThrowsAsync <InvalidEmailFormatException>(
                async() => await handler.Handle(command, CancellationToken.None));

            Assert.AreEqual(invalidEmail, exception.Email);
        }
Exemplo n.º 15
0
        public void AuthenticateCommand_PresentNewEmail_ThrowsException()
        {
            // ---- Arrange ----

            const string email    = "*****@*****.**";
            const string password = "******";
            var          command  = new AuthenticateUserCommand(email, password);
            var          handler  = new AuthenticateUserCommandHandler(_repositoryProviderMock.Object, _configuration);

            // ---- Act & Assert ----

            var exception = Assert.ThrowsAsync <UserNotFoundByEmailException>(
                async() => await handler.Handle(command, CancellationToken.None));

            _authRepositoryMock.Verify(r => r.GetUserIdentity(email), Times.Once);
            StringAssert.AreEqualIgnoringCase(email, exception.Email);
        }
        public async Task ShouldChangePasswordSaltAndReHashPasswordOnSuccesfulAuth()
        {
            var dbContext  = InfrastructureFactory.GetInMemoryContext(nameof(ShouldChangePasswordSaltAndReHashPasswordOnSuccesfulAuth));
            var unitOfWork = InfrastructureFactory.GetEfUnitOfWork(dbContext);
            var user       = EntityFactory.GetUser("johndoe", "Pass@123");
            await unitOfWork.AddAndSaveAsync(user);

            var salt          = user.PasswordSalt;
            var passwordHash  = user.PasswordHash;
            var lastLoginDate = user.LastLoginDate;

            var handler        = new AuthenticateUserCommandHandler(unitOfWork, InfrastructureFactory.GetSha1Hasher(), InfrastructureFactory.GetMachineDateTime());
            var authentication = await handler.Handle(new AuthenticateUserCommand("johndoe", "Pass@123", UserAuthConstants.TokenExpirationTime), default);

            user = await unitOfWork.GetSingleAsync <UserEntity>(u => u.Nickname == "johndoe");

            Assert.AreNotEqual(salt, user.PasswordSalt);
            Assert.AreNotEqual(passwordHash, user.PasswordSalt);
            Assert.AreNotEqual(lastLoginDate, user.LastLoginDate);
        }
Exemplo n.º 17
0
        public async Task Handle_GivenUserDoesExistAndPasswordDoesVerifyButHasNoAppSetUpAndNoDeviceSetUp_ExpectSuccessfulResultWithAwaitingMfaEmailCodeStateDomainEventRaisedAndAPartialAttemptLogged()
        {
            var user   = new Mock <IUser>();
            var userId = Guid.NewGuid();

            user.Setup(x => x.Id).Returns(userId);
            user.Setup(x => x.EmailAddress).Returns("email-address");
            user.Setup(x => x.PasswordHash).Returns(BCrypt.Net.BCrypt.HashPassword("password"));
            user.Setup(x => x.AuthenticatorApps).Returns(new List <AuthenticatorApp>());
            user.Setup(x => x.AuthenticatorDevices).Returns(new List <AuthenticatorDevice>());
            user.Setup(x => x.IsVerified).Returns(true);
            user.Setup(x => x.Profile).Returns(new Profile(Guid.NewGuid(), "first-name", "last-name"));

            var userRepository = new Mock <IUserRepository>();
            var unitOfWork     = new Mock <IUnitOfWork>();

            unitOfWork.Setup(x => x.SaveEntitiesAsync(It.IsAny <CancellationToken>())).ReturnsAsync(() => true);
            userRepository.Setup(x => x.UnitOfWork).Returns(unitOfWork.Object);
            userRepository.Setup(x => x.FindByEmailAddress(It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(() => Maybe.From(user.Object));

            var clock = new Mock <IClock>();

            var securitySettings = new Mock <IOptions <SecuritySettings> >();

            securitySettings.Setup(x => x.Value).Returns(new SecuritySettings());

            var fido = new Mock <IFido2>();

            var handler = new AuthenticateUserCommandHandler(userRepository.Object, clock.Object, securitySettings.Object, fido.Object);
            var cmd     = new AuthenticateUserCommand("email-address", "password");
            var result  = await handler.Handle(cmd, CancellationToken.None);

            Assert.True(result.IsSuccess);
            Assert.Equal(userId, result.Value.UserId);
            Assert.False(result.Value.SetupMfaProviders.HasFlag(MfaProvider.App));
            Assert.True(result.Value.SetupMfaProviders.HasFlag(MfaProvider.Email));
            Assert.Equal(BaseAuthenticationProcessCommandResult.AuthenticationState.AwaitingMfaEmailCode, result.Value.AuthenticationStatus);
            user.Verify(x => x.ProcessPartialSuccessfulAuthenticationAttempt(It.IsAny <DateTime>(), AuthenticationHistoryType.EmailMfaRequested));
            user.Verify(x => x.AddDomainEvent(It.IsAny <EmailMfaTokenGeneratedEvent>()));
        }
Exemplo n.º 18
0
        public async Task Handle_GivenUserDoesNotExist_ExpectFailedResult()
        {
            var userRepository = new Mock <IUserRepository>();
            var unitOfWork     = new Mock <IUnitOfWork>();

            unitOfWork.Setup(x => x.SaveEntitiesAsync(It.IsAny <CancellationToken>())).ReturnsAsync(() => true);
            userRepository.Setup(x => x.UnitOfWork).Returns(unitOfWork.Object);
            userRepository.Setup(x => x.FindByEmailAddress(It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(() => Maybe <IUser> .Nothing);

            var clock = new Mock <IClock>();

            var securitySettings = new Mock <IOptions <SecuritySettings> >();
            var fido             = new Mock <IFido2>();

            var handler = new AuthenticateUserCommandHandler(userRepository.Object, clock.Object, securitySettings.Object, fido.Object);
            var cmd     = new AuthenticateUserCommand("email-address", "password");
            var result  = await handler.Handle(cmd, CancellationToken.None);

            Assert.True(result.IsFailure);
            Assert.Equal(ErrorCodes.UserNotFound, result.Error.Code);
        }