def test_user_not_found(self):
     user = User.testing_create()
     jwt_auth = auth.JwtRequestLoader(flask.current_app)
     token = jwt_auth.create_access_token(user)
     User.delete_cascaded()
     with mock.patch.dict(
         flask.current_app.config,
         JWT_TOKEN_LOCATION='query_string',
         JWT_QUERY_STRING_NAME='jwt',
     ):
         with flask.current_app.test_request_context('/?jwt={}'.format(token)):
             assert jwt_auth.get_authenticated_user() is None
 def test_user_bad_password(self):
     user = User.testing_create()
     with pytest.raises(auth.UserInvalidAuth) as e_info:
         authenticator = auth.KegAuthenticator(app=flask.current_app)
         authenticator.verify_user(login_id=user.email,
                                   password='******')
     assert e_info.value.user is user
    def test_char_set_validator_failures(self, pw):
        user = User.testing_create()

        with pytest.raises(
            auth.PasswordPolicyError,
            match='Password must include at least 3 of lowercase letter, uppercase letter, number and/or symbol'  # noqa: E501
        ):
            auth.PasswordPolicy().check_character_set(pw, user)
    def test_user_not_found(self, mocked_ldap):
        mocked_ldap.return_value.simple_bind_s.return_value = (ldap.RES_BIND, )

        authenticator = auth.LdapAuthenticator(app=flask.current_app)
        success = authenticator.verify_user(login_id='nobodybythisnamehere', password='******')
        assert mocked_ldap.call_count
        assert success
        assert User.get_by(username='******')
    def test_no_dn_format_set(self, mocked_ldap):
        del flask.current_app.config['KEGAUTH_LDAP_DN_FORMAT']

        user = User.testing_create()
        authenticator = auth.LdapAuthenticator(app=flask.current_app)
        with pytest.raises(Exception) as e_info:
            authenticator.verify_password(user, None)
        assert 'KEGAUTH_LDAP_DN_FORMAT' in str(e_info.value)
    def test_debug_override(self, mocked_ldap):
        flask.current_app.config['KEGAUTH_LDAP_TEST_MODE'] = True

        user = User.testing_create()
        authenticator = auth.LdapAuthenticator(app=flask.current_app)
        success = authenticator.verify_password(user, 'foo')

        assert not mocked_ldap.call_count
        assert success is True
    def test_unsuccessful_authentication(self, mocked_ldap):
        mocked_ldap.return_value.simple_bind_s.side_effect = ldap.INVALID_CREDENTIALS()

        user = User.testing_create()
        authenticator = auth.LdapAuthenticator(app=flask.current_app)
        success = authenticator.verify_password(user, 'foo')

        assert mocked_ldap.call_count
        assert success is False
    def test_successful_authentication(self, mocked_ldap):
        mocked_ldap.return_value.simple_bind_s.return_value = (ldap.RES_BIND, )

        user = User.testing_create()
        authenticator = auth.LdapAuthenticator(app=flask.current_app)
        success = authenticator.verify_password(user, 'foo')

        assert mocked_ldap.call_count
        assert success is True
    def test_invalid_dn_syntax(self, mocked_ldap):
        mocked_ldap.return_value.simple_bind_s.side_effect = ldap.INVALID_DN_SYNTAX()

        user = User.testing_create()
        authenticator = auth.LdapAuthenticator(app=flask.current_app)
        success = authenticator.verify_password(user, 'foo')

        assert mocked_ldap.call_count
        assert success is False
    def test_required_char_types_one_type(self):
        user = User.testing_create()

        class RequireNumber(auth.PasswordPolicy):
            required_min_char_types = 1
            required_char_types = [auth.PasswordCharset('number', string.digits)]

        with pytest.raises(auth.PasswordPolicyError, match='Password must include a number'):
            RequireNumber().check_character_set('abcdefgh', user)

        RequireNumber().check_character_set('abcdefg1', user)
    def test_unverified_user(self):
        user = User.testing_create()
        user.is_verified = False
        authenticator = auth.KegAuthenticator(app=flask.current_app)
        with pytest.raises(auth.UserInactive) as e_info:
            authenticator.verify_user(login_id=user.email, password=user._plaintext_pass)
        assert e_info.value.user is user

        found_user = authenticator.verify_user(login_id=user.email, password=user._plaintext_pass,
                                               allow_unverified=True)
        assert user is found_user
    def test_override_required_char_types_success(self, pw):
        user = User.testing_create()

        class RequireWhitespace(auth.PasswordPolicy):
            required_min_char_types = 4
            required_char_types = [
                *auth.PasswordPolicy.required_char_types,
                auth.PasswordCharset('whitespace', string.whitespace)
            ]

        RequireWhitespace().check_character_set(pw, user)
    def test_override_min_char_types_requirement_failures(self, pw):
        user = User.testing_create()

        class FewerChars(auth.PasswordPolicy):
            required_min_char_types = 2

        with pytest.raises(
            auth.PasswordPolicyError,
            match='Password must include at least 2 of lowercase letter, uppercase letter, number and/or symbol'  # noqa: E501
        ):
            FewerChars().check_character_set(pw, user)
    def test_check_length(self):
        user = User.testing_create()
        with pytest.raises(auth.PasswordPolicyError,
                           match='Password must be at least 8 characters long'):
            auth.PasswordPolicy().check_length('aBcDe1!', user)

        class LongerPolicy(auth.PasswordPolicy):
            min_length = 10

        with pytest.raises(auth.PasswordPolicyError,
                           match='Password must be at least 10 characters long'):
            LongerPolicy().check_length('aBcDeFg1!', user)

        auth.PasswordPolicy().check_length('aBcDeF1!', user)
        LongerPolicy().check_length('aBcDeFgH1!', user)
    def test_override_required_char_types_failures(self, pw):
        user = User.testing_create()

        class RequireWhitespace(auth.PasswordPolicy):
            required_min_char_types = 4
            required_char_types = [
                *auth.PasswordPolicy.required_char_types,
                auth.PasswordCharset('whitespace', string.whitespace)
            ]

        with pytest.raises(
            auth.PasswordPolicyError,
            match='Password must include at least 4 of lowercase letter, uppercase letter, number, symbol and/or whitespace'  # noqa: E501
        ):
            RequireWhitespace().check_character_set(pw, user)
    def test_successful_authentication_multiple_server_urls(self, mocked_ldap):
        flask.current_app.config['KEGAUTH_LDAP_SERVER_URL'] = [
            'abc123', 'def456', 'ghi789'
        ]
        mocked_ldap.return_value.simple_bind_s.side_effect = ((0, ), (0, ), (
            ldap.RES_BIND, ))

        user = User.testing_create()
        authenticator = auth.LdapAuthenticator(app=flask.current_app)
        success = authenticator.verify_password(user, 'foo')

        assert mocked_ldap.call_args_list == [
            mock.call('abc123'),
            mock.call('def456'),
            mock.call('ghi789'),
        ]
        assert success is True
 def test_create_access_token(self):
     user = User.testing_create()
     jwt_auth = auth.JwtRequestLoader(flask.current_app)
     token = jwt_auth.create_access_token(user)
     assert flask_jwt_extended.decode_token(
         token)['sub'] == user.session_key
 def test_user_not_active(self, mocked_ldap):
     # internal flag should have no effect on LDAP auth
     mocked_ldap.return_value.simple_bind_s.return_value = (ldap.RES_BIND, )
     user = User.testing_create(is_enabled=False)
     authenticator = auth.LdapAuthenticator(app=flask.current_app)
     assert authenticator.verify_user(login_id=user.email)
 def test_check_does_not_contain_username_email_success(self, pw, email):
     user = User.testing_create(email=email)
     auth.PasswordPolicy().check_does_not_contain_username(pw, user)
 def test_check_does_not_contain_username_email_failures(self, pw, email):
     user = User.testing_create(email=email)
     with pytest.raises(auth.PasswordPolicyError,
                        match='Password may not contain username'):
         auth.PasswordPolicy().check_does_not_contain_username(pw, user)
 def test_check_char_set_success(self, pw):
     user = User.testing_create()
     auth.PasswordPolicy().check_character_set(pw, user)
 def test_user_verified(self):
     user = User.testing_create()
     authenticator = auth.KegAuthenticator(app=flask.current_app)
     found_user = authenticator.verify_user(login_id=user.email,
                                            password=user._plaintext_pass)
     assert user is found_user
 def setup_method(self, _):
     User.delete_cascaded()
     UserNoEmail.delete_cascaded()
 def test_user_not_active(self):
     user = User.testing_create(is_enabled=False)
     with pytest.raises(auth.UserInactive) as e_info:
         authenticator = auth.KegAuthenticator(app=flask.current_app)
         authenticator.verify_user(login_id=user.email)
     assert e_info.value.user is user