Пример #1
0
def test_login():
    """
    This tests if we can log in successfully or fail correctly.

    """

    try:
        os.remove("test-login.authdb.sqlite")
    except Exception:
        pass
    try:
        os.remove("test-login.authdb.sqlite-shm")
    except Exception:
        pass
    try:
        os.remove("test-login.authdb.sqlite-wal")
    except Exception:
        pass

    get_test_authdb()
    get_public_suffix_list()

    # create the user
    user_payload = {
        "full_name": "Test User",
        "email": "*****@*****.**",
        "password": "******",
        "pii_salt": "super-secret-salt",
        "reqid": 1,
    }
    user_created = actions.create_new_user(
        user_payload,
        override_authdb_path="sqlite:///test-login.authdb.sqlite")
    assert user_created["success"] is True
    assert user_created["user_email"] == "*****@*****.**"
    assert ("User account created. Please verify your email address to log in."
            in user_created["messages"])

    # create a new session token
    session_payload = {
        "user_id": 2,
        "user_agent": "Mozzarella Killerwhale",
        "expires": datetime.utcnow() + timedelta(hours=1),
        "ip_address": "1.1.1.1",
        "extra_info_json": {
            "pref_datasets_always_private": True
        },
        "pii_salt": "super-secret-salt",
        "reqid": 1,
    }

    # check creation of session
    session_token1 = actions.auth_session_new(
        session_payload,
        override_authdb_path="sqlite:///test-login.authdb.sqlite",
    )
    assert session_token1["success"] is True
    assert session_token1["session_token"] is not None

    # try logging in now with correct password
    login = actions.auth_user_login(
        {
            "session_token": session_token1["session_token"],
            "email": user_payload["email"],
            "password": user_payload["password"],
            "pii_salt": "super-secret-salt",
            "reqid": 1,
        },
        override_authdb_path="sqlite:///test-login.authdb.sqlite",
    )

    # this should fail because we haven't verified our email yet
    assert login["success"] is False

    # verify our email
    emailverify = actions.set_user_emailaddr_verified(
        {
            "email": user_payload["email"],
            "user_id": user_created["user_id"],
            "pii_salt": "super-secret-salt",
            "reqid": 1,
        },
        override_authdb_path="sqlite:///test-login.authdb.sqlite",
    )

    assert emailverify["success"] is True
    assert emailverify["user_id"] == user_created["user_id"]
    assert emailverify["is_active"] is True
    assert emailverify["user_role"] == "authenticated"

    # now make a new session token
    session_payload = {
        "user_id": emailverify["user_id"],
        "user_agent": "Mozzarella Killerwhale",
        "expires": datetime.utcnow() + timedelta(hours=1),
        "ip_address": "1.1.1.1",
        "extra_info_json": {
            "pref_datasets_always_private": True
        },
        "pii_salt": "super-secret-salt",
        "reqid": 1,
    }

    # check creation of session
    session_token2 = actions.auth_session_new(
        session_payload,
        override_authdb_path="sqlite:///test-login.authdb.sqlite",
    )
    assert session_token2["success"] is True
    assert session_token2["session_token"] is not None

    # and now try to log in again
    login = actions.auth_user_login(
        {
            "session_token": session_token2["session_token"],
            "email": user_payload["email"],
            "password": user_payload["password"],
            "pii_salt": "super-secret-salt",
            "reqid": 1,
        },
        override_authdb_path="sqlite:///test-login.authdb.sqlite",
    )

    assert login["success"] is True

    # try logging in now with the wrong password
    login = actions.auth_user_login(
        {
            "session_token": session_token2["session_token"],
            "email": user_payload["email"],
            "password": "******",
            "pii_salt": "super-secret-salt",
            "reqid": 1,
        },
        override_authdb_path="sqlite:///test-login.authdb.sqlite",
    )
    assert login["success"] is False

    # tests for no session token provided
    login = actions.auth_user_login(
        {
            "session_token": "correcthorsebatterystaple",
            "email": user_payload["email"],
            "password": user_payload["password"],
            "pii_salt": "super-secret-salt",
            "reqid": 1,
        },
        override_authdb_path="sqlite:///test-login.authdb.sqlite",
    )
    assert login["success"] is False

    try:
        os.remove("test-login.authdb.sqlite")
    except Exception:
        pass
    try:
        os.remove("test-login.authdb.sqlite-shm")
    except Exception:
        pass
    try:
        os.remove("test-login.authdb.sqlite-wal")
    except Exception:
        pass
def test_login_logout():

    """
    See if we can login and log out correctly.

    """

    try:
        os.remove("test-loginlogout.authdb.sqlite")
    except Exception:
        pass
    try:
        os.remove("test-loginlogout.authdb.sqlite-shm")
    except Exception:
        pass
    try:
        os.remove("test-loginlogout.authdb.sqlite-wal")
    except Exception:
        pass

    get_test_authdb()
    get_public_suffix_list()

    # create the user
    user_payload = {
        "full_name": "Test User",
        "email": "*****@*****.**",
        "password": "******",
        "pii_salt": "super-secret-salt",
        "reqid": 1,
    }
    user_created = actions.create_new_user(
        user_payload,
        override_authdb_path="sqlite:///test-loginlogout.authdb.sqlite",
    )
    assert user_created["success"] is True
    assert user_created["user_email"] == "*****@*****.**"
    assert (
        "User account created. Please verify your email address to log in."
        in user_created["messages"]
    )

    # create a new session token
    session_payload = {
        "user_id": 2,
        "user_agent": "Mozzarella Killerwhale",
        "expires": datetime.utcnow() + timedelta(hours=1),
        "ip_address": "1.1.1.1",
        "extra_info_json": {"pref_datasets_always_private": True},
        "pii_salt": "super-secret-salt",
        "reqid": 1,
    }

    # check creation of session
    session_token1 = actions.auth_session_new(
        session_payload,
        override_authdb_path="sqlite:///test-loginlogout.authdb.sqlite",
        raiseonfail=True,
    )
    assert session_token1["success"] is True
    assert session_token1["session_token"] is not None

    # try logging in now with correct password
    login = actions.auth_user_login(
        {
            "session_token": session_token1["session_token"],
            "email": user_payload["email"],
            "password": user_payload["password"],
            "pii_salt": "super-secret-salt",
            "reqid": 1,
        },
        override_authdb_path="sqlite:///test-loginlogout.authdb.sqlite",
        raiseonfail=True,
    )

    # this should fail because we haven't verified our email yet
    assert login["success"] is False

    # verify our email
    emailverify = actions.set_user_emailaddr_verified(
        {
            "email": user_payload["email"],
            "user_id": user_created["user_id"],
            "pii_salt": "super-secret-salt",
            "reqid": 1,
        },
        override_authdb_path="sqlite:///test-loginlogout.authdb.sqlite",
        raiseonfail=True,
    )

    assert emailverify["success"] is True
    assert emailverify["user_id"] == user_created["user_id"]
    assert emailverify["is_active"] is True
    assert emailverify["user_role"] == "authenticated"

    # now make a new session token
    session_payload = {
        "user_id": 2,
        "user_agent": "Mozzarella Killerwhale",
        "expires": datetime.utcnow() + timedelta(hours=1),
        "ip_address": "1.1.1.1",
        "extra_info_json": {"pref_datasets_always_private": True},
        "pii_salt": "super-secret-salt",
        "reqid": 1,
    }

    # check creation of session
    session_token2 = actions.auth_session_new(
        session_payload,
        override_authdb_path="sqlite:///test-loginlogout.authdb.sqlite",
        raiseonfail=True,
    )
    assert session_token2["success"] is True
    assert session_token2["session_token"] is not None

    # and now try to log in again
    login = actions.auth_user_login(
        {
            "session_token": session_token2["session_token"],
            "email": user_payload["email"],
            "password": user_payload["password"],
            "pii_salt": "super-secret-salt",
            "reqid": 1,
        },
        override_authdb_path="sqlite:///test-loginlogout.authdb.sqlite",
        raiseonfail=True,
    )

    assert login["success"] is True

    # make sure the session token we used to log in is gone
    # check if our session was deleted correctly
    session_still_exists = actions.auth_session_exists(
        {
            "session_token": session_token2["session_token"],
            "pii_salt": "super-secret-salt",
            "reqid": 1,
        },
        override_authdb_path="sqlite:///test-loginlogout.authdb.sqlite",
    )
    assert session_still_exists["success"] is False

    # start a new session with this user's user ID
    authenticated_session_token = actions.auth_session_new(
        {
            "user_id": login["user_id"],
            "user_agent": "Mozzarella Killerwhale",
            "expires": datetime.utcnow() + timedelta(hours=1),
            "ip_address": "1.1.1.1",
            "extra_info_json": {"pref_datasets_always_private": True},
            "pii_salt": "super-secret-salt",
            "reqid": 1,
        },
        override_authdb_path="sqlite:///test-loginlogout.authdb.sqlite",
        raiseonfail=True,
    )

    # now see if we can log out
    logged_out = actions.auth_user_logout(
        {
            "session_token": authenticated_session_token["session_token"],
            "user_id": login["user_id"],
            "pii_salt": "super-secret-salt",
            "reqid": 1,
        },
        override_authdb_path="sqlite:///test-loginlogout.authdb.sqlite",
        raiseonfail=True,
    )

    assert logged_out["success"] is True

    # check if our session was deleted correctly
    session_still_exists = actions.auth_session_exists(
        {
            "session_token": authenticated_session_token,
            "pii_salt": "super-secret-salt",
            "reqid": 1,
        },
        override_authdb_path="sqlite:///test-loginlogout.authdb.sqlite",
        raiseonfail=True,
    )

    assert session_still_exists["success"] is False

    try:
        os.remove("test-loginlogout.authdb.sqlite")
    except Exception:
        pass
    try:
        os.remove("test-loginlogout.authdb.sqlite-shm")
    except Exception:
        pass
    try:
        os.remove("test-loginlogout.authdb.sqlite-wal")
    except Exception:
        pass
Пример #3
0
def test_sessions():
    '''
    This tests session token generation, readback, deletion, and expiry.

    '''

    try:
        os.remove('test-creation.authdb.sqlite')
    except Exception:
        pass
    try:
        os.remove('test-creation.authdb.sqlite-shm')
    except Exception:
        pass
    try:
        os.remove('test-creation.authdb.sqlite-wal')
    except Exception:
        pass

    get_test_authdb()

    # session token payload
    session_payload = {
        'user_id': 2,
        'user_agent': 'Mozzarella Killerwhale',
        'expires': datetime.utcnow() + timedelta(hours=1),
        'ip_address': '1.2.3.4',
        'extra_info_json': {
            'pref_datasets_always_private': True
        }
    }

    # check creation
    session_token1 = actions.auth_session_new(
        session_payload,
        override_authdb_path='sqlite:///test-creation.authdb.sqlite')
    assert session_token1['success'] is True
    assert session_token1['session_token'] is not None

    # check deletion
    deleted = actions.auth_session_delete(
        {'session_token': session_token1['session_token']},
        override_authdb_path='sqlite:///test-creation.authdb.sqlite')
    assert deleted['success'] is True

    # check readback of deleted
    check = actions.auth_session_exists(
        {'session_token': session_token1['session_token']},
        override_authdb_path='sqlite:///test-creation.authdb.sqlite')
    assert check['success'] is False

    # new session token payload
    session_payload = {
        'user_id': 2,
        'user_agent': 'Mozzarella Killerwhale',
        'expires': datetime.utcnow() + timedelta(hours=1),
        'ip_address': '1.2.3.4',
        'extra_info_json': {
            'pref_datasets_always_private': True
        }
    }

    # check creation
    session_token2 = actions.auth_session_new(
        session_payload,
        override_authdb_path='sqlite:///test-creation.authdb.sqlite')
    assert session_token2['success'] is True
    assert session_token2['session_token'] is not None
    assert session_token1['session_token'] != session_token2['session_token']

    # get items for session_token
    check = actions.auth_session_exists(
        {'session_token': session_token2['session_token']},
        override_authdb_path='sqlite:///test-creation.authdb.sqlite')

    assert check['success'] is True

    for key in ('user_id', 'full_name', 'email', 'email_verified',
                'emailverify_sent_datetime', 'is_active', 'last_login_try',
                'last_login_success', 'created_on', 'user_role',
                'session_token', 'ip_address', 'user_agent', 'created',
                'expires', 'extra_info_json'):
        assert key in check['session_info']

    assert check['session_info']['user_id'] == 2
    assert check['session_info'][
        'full_name'] == 'The systemwide anonymous user'
    assert check['session_info']['email'] == 'anonuser@localhost'
    assert check['session_info']['email_verified'] is True
    assert check['session_info']['is_active'] is True
    assert check['session_info']['last_login_try'] is None
    assert check['session_info']['last_login_success'] is None
    assert check['session_info']['user_role'] == 'anonymous'
    assert check['session_info']['session_token'] == session_token2[
        'session_token']
    assert check['session_info']['ip_address'] == session_payload['ip_address']
    assert check['session_info']['user_agent'] == session_payload['user_agent']
    assert check['session_info']['expires'] == session_payload['expires']
    assert check['session_info']['extra_info_json'] == session_payload[
        'extra_info_json']

    # new session token payload
    session_payload = {
        'user_id': 2,
        'user_agent': 'Mozzarella Killerwhale',
        'expires': datetime.utcnow() + timedelta(seconds=5),
        'ip_address': '1.2.3.4',
        'extra_info_json': {
            'pref_datasets_always_private': True
        }
    }

    # check creation
    session_token3 = actions.auth_session_new(
        session_payload,
        override_authdb_path='sqlite:///test-creation.authdb.sqlite')
    assert session_token3['success'] is True
    assert session_token3['session_token'] is not None
    assert session_token3['session_token'] != session_token2['session_token']

    # check readback when expired
    time.sleep(10.0)

    check = actions.auth_session_exists(
        {'session_token': session_token3['session_token']},
        override_authdb_path='sqlite:///test-creation.authdb.sqlite')

    assert check['success'] is False

    try:
        os.remove('test-creation.authdb.sqlite')
    except Exception:
        pass
    try:
        os.remove('test-creation.authdb.sqlite-shm')
    except Exception:
        pass
    try:
        os.remove('test-creation.authdb.sqlite-wal')
    except Exception:
        pass
Пример #4
0
def test_login_timing():
    """This tests obfuscating the presence/absence of users based on password
    checks.

    This may fail randomly if the testing service is under load.

    """

    try:
        os.remove("test-timing.authdb.sqlite")
    except Exception:
        pass
    try:
        os.remove("test-timing.authdb.sqlite-shm")
    except Exception:
        pass
    try:
        os.remove("test-timing.authdb.sqlite-wal")
    except Exception:
        pass

    get_test_authdb()
    get_public_suffix_list()

    # create the user
    user_payload = {
        "full_name": "Test User",
        "email": "*****@*****.**",
        "password": "******",
        "pii_salt": "super-secret-salt",
        "reqid": 1,
    }
    user_created = actions.create_new_user(
        user_payload,
        override_authdb_path="sqlite:///test-timing.authdb.sqlite",
    )
    assert user_created["success"] is True
    assert user_created["user_email"] == "*****@*****.**"
    assert ("User account created. Please verify your email address to log in."
            in user_created["messages"])

    # create a new session token
    session_payload = {
        "user_id": 2,
        "user_agent": "Mozzarella Killerwhale",
        "expires": datetime.utcnow() + timedelta(hours=1),
        "ip_address": "1.1.1.1",
        "extra_info_json": {
            "pref_datasets_always_private": True
        },
        "pii_salt": "super-secret-salt",
        "reqid": 1,
    }

    # check creation of session
    session_token1 = actions.auth_session_new(
        session_payload,
        override_authdb_path="sqlite:///test-timing.authdb.sqlite",
    )
    assert session_token1["success"] is True
    assert session_token1["session_token"] is not None

    # try logging in now with correct password
    login = actions.auth_user_login(
        {
            "session_token": session_token1["session_token"],
            "email": user_payload["email"],
            "password": user_payload["password"],
            "pii_salt": "super-secret-salt",
            "reqid": 1,
        },
        override_authdb_path="sqlite:///test-timing.authdb.sqlite",
    )

    # this should fail because we haven't verified our email yet
    assert login["success"] is False

    # verify our email
    emailverify = actions.set_user_emailaddr_verified(
        {
            "email": user_payload["email"],
            "user_id": user_created["user_id"],
            "pii_salt": "super-secret-salt",
            "reqid": 1,
        },
        override_authdb_path="sqlite:///test-timing.authdb.sqlite",
    )

    assert emailverify["success"] is True
    assert emailverify["user_id"] == user_created["user_id"]
    assert emailverify["is_active"] is True
    assert emailverify["user_role"] == "authenticated"

    # now make a new session token
    session_payload = {
        "user_id": 2,
        "user_agent": "Mozzarella Killerwhale",
        "expires": datetime.utcnow() + timedelta(hours=1),
        "ip_address": "1.1.1.1",
        "extra_info_json": {
            "pref_datasets_always_private": True
        },
        "pii_salt": "super-secret-salt",
        "reqid": 1,
    }

    # check creation of session
    session_token2 = actions.auth_session_new(
        session_payload,
        override_authdb_path="sqlite:///test-timing.authdb.sqlite",
    )
    assert session_token2["success"] is True
    assert session_token2["session_token"] is not None

    # and now try to log in again
    login = actions.auth_user_login(
        {
            "session_token": session_token2["session_token"],
            "email": user_payload["email"],
            "password": user_payload["password"],
            "pii_salt": "super-secret-salt",
            "reqid": 1,
        },
        override_authdb_path="sqlite:///test-timing.authdb.sqlite",
    )

    assert login["success"] is True

    # basic tests for timing attacks

    # incorrect passwords
    incorrect_timings = []
    for _ in range(500):

        # now make a new session token
        session_payload = {
            "user_id": 2,
            "user_agent": "Mozzarella Killerwhale",
            "expires": datetime.utcnow() + timedelta(hours=1),
            "ip_address": "1.1.1.1",
            "extra_info_json": {
                "pref_datasets_always_private": True
            },
            "pii_salt": "super-secret-salt",
            "reqid": 1,
        }

        # check creation of session
        session_token2 = actions.auth_session_new(
            session_payload,
            override_authdb_path="sqlite:///test-timing.authdb.sqlite",
        )

        start = time.time()
        actions.auth_user_login(
            {
                "session_token": session_token2["session_token"],
                "email": user_payload["email"],
                "password": secrets.token_urlsafe(16),
                "pii_salt": "super-secret-salt",
                "reqid": 1,
            },
            override_authdb_path="sqlite:///test-timing.authdb.sqlite",
        )
        end = time.time()
        incorrect_timings.append(end - start)

    # correct passwords
    correct_timings = []
    for _ in range(500):

        # now make a new session token
        session_payload = {
            "user_id": 2,
            "user_agent": "Mozzarella Killerwhale",
            "expires": datetime.utcnow() + timedelta(hours=1),
            "ip_address": "1.1.1.1",
            "extra_info_json": {
                "pref_datasets_always_private": True
            },
            "pii_salt": "super-secret-salt",
            "reqid": 1,
        }

        # check creation of session
        session_token2 = actions.auth_session_new(
            session_payload,
            override_authdb_path="sqlite:///test-timing.authdb.sqlite",
        )

        start = time.time()
        actions.auth_user_login(
            {
                "session_token": session_token2["session_token"],
                "email": user_payload["email"],
                "password": user_payload["password"],
                "pii_salt": "super-secret-salt",
                "reqid": 1,
            },
            override_authdb_path="sqlite:///test-timing.authdb.sqlite",
        )
        end = time.time()
        correct_timings.append(end - start)

    # wronguser passwords
    wronguser_timings = []
    for _ in range(500):

        # now make a new session token
        session_payload = {
            "user_id": 2,
            "user_agent": "Mozzarella Killerwhale",
            "expires": datetime.utcnow() + timedelta(hours=1),
            "ip_address": "1.1.1.1",
            "extra_info_json": {
                "pref_datasets_always_private": True
            },
            "pii_salt": "super-secret-salt",
            "reqid": 1,
        }

        # check creation of session
        session_token2 = actions.auth_session_new(
            session_payload,
            override_authdb_path="sqlite:///test-timing.authdb.sqlite",
        )

        start = time.time()
        actions.auth_user_login(
            {
                "session_token": session_token2["session_token"],
                "email": secrets.token_urlsafe(16),
                "password": secrets.token_urlsafe(16),
                "pii_salt": "super-secret-salt",
                "reqid": 1,
            },
            override_authdb_path="sqlite:///test-timing.authdb.sqlite",
        )
        end = time.time()
        wronguser_timings.append(end - start)

    # broken requests
    broken_timings = []
    for _ in range(500):

        # now make a new session token
        session_payload = {
            "user_id": 2,
            "user_agent": "Mozzarella Killerwhale",
            "expires": datetime.utcnow() + timedelta(hours=1),
            "ip_address": "1.1.1.1",
            "extra_info_json": {
                "pref_datasets_always_private": True
            },
            "pii_salt": "super-secret-salt",
            "reqid": 1,
        }

        # check creation of session
        session_token2 = actions.auth_session_new(
            session_payload,
            override_authdb_path="sqlite:///test-timing.authdb.sqlite",
        )

        start = time.time()
        actions.auth_user_login(
            {
                "session_token": "correcthorsebatterystaple",
                "email": user_payload["email"],
                "password": user_payload["password"],
                "pii_salt": "super-secret-salt",
                "reqid": 1,
            },
            override_authdb_path="sqlite:///test-timing.authdb.sqlite",
        )
        end = time.time()
        broken_timings.append(end - start)

    correct_median = statistics.median(correct_timings)
    incorrect_median = statistics.median(incorrect_timings)
    broken_median = statistics.median(broken_timings)
    wronguser_median = statistics.median(wronguser_timings)

    # all timings should match within 10 milliseconds or so
    assert abs(correct_median - incorrect_median) < 0.01
    assert abs(correct_median - broken_median) < 0.01
    assert abs(correct_median - wronguser_median) < 0.01

    try:
        os.remove("test-timing.authdb.sqlite")
    except Exception:
        pass
    try:
        os.remove("test-timing.authdb.sqlite-shm")
    except Exception:
        pass
    try:
        os.remove("test-timing.authdb.sqlite-wal")
    except Exception:
        pass
Пример #5
0
def test_login_logout():
    '''
    See if we can login and log out correctly.

    '''

    try:
        os.remove('test-loginlogout.authdb.sqlite')
    except Exception as e:
        pass
    try:
        os.remove('test-loginlogout.authdb.sqlite-shm')
    except Exception as e:
        pass
    try:
        os.remove('test-loginlogout.authdb.sqlite-wal')
    except Exception as e:
        pass

    get_test_authdb()

    # create the user
    user_payload = {
        'full_name': 'Test User',
        'email': '*****@*****.**',
        'password': '******'
    }
    user_created = actions.create_new_user(
        user_payload,
        override_authdb_path='sqlite:///test-loginlogout.authdb.sqlite')
    assert user_created['success'] is True
    assert user_created['user_email'] == '*****@*****.**'
    assert ('User account created. Please verify your email address to log in.'
            in user_created['messages'])

    # create a new session token
    session_payload = {
        'user_id': 2,
        'user_agent': 'Mozzarella Killerwhale',
        'expires': datetime.utcnow() + timedelta(hours=1),
        'ip_address': '1.1.1.1',
        'extra_info_json': {
            'pref_datasets_always_private': True
        }
    }

    # check creation of session
    session_token1 = actions.auth_session_new(
        session_payload,
        override_authdb_path='sqlite:///test-loginlogout.authdb.sqlite',
        raiseonfail=True)
    assert session_token1['success'] is True
    assert session_token1['session_token'] is not None

    # try logging in now with correct password
    login = actions.auth_user_login(
        {
            'session_token': session_token1['session_token'],
            'email': user_payload['email'],
            'password': user_payload['password']
        },
        override_authdb_path='sqlite:///test-loginlogout.authdb.sqlite',
        raiseonfail=True)

    # this should fail because we haven't verified our email yet
    assert login['success'] is False

    # verify our email
    emailverify = (actions.verify_user_email_address(
        {
            'email': user_payload['email'],
            'user_id': user_created['user_id']
        },
        override_authdb_path='sqlite:///test-loginlogout.authdb.sqlite',
        raiseonfail=True))

    assert emailverify['success'] is True
    assert emailverify['user_id'] == user_created['user_id']
    assert emailverify['is_active'] is True
    assert emailverify['user_role'] == 'authenticated'

    # now make a new session token
    session_payload = {
        'user_id': 2,
        'user_agent': 'Mozzarella Killerwhale',
        'expires': datetime.utcnow() + timedelta(hours=1),
        'ip_address': '1.1.1.1',
        'extra_info_json': {
            'pref_datasets_always_private': True
        }
    }

    # check creation of session
    session_token2 = actions.auth_session_new(
        session_payload,
        override_authdb_path='sqlite:///test-loginlogout.authdb.sqlite',
        raiseonfail=True)
    assert session_token2['success'] is True
    assert session_token2['session_token'] is not None

    # and now try to log in again
    login = actions.auth_user_login(
        {
            'session_token': session_token2['session_token'],
            'email': user_payload['email'],
            'password': user_payload['password']
        },
        override_authdb_path='sqlite:///test-loginlogout.authdb.sqlite',
        raiseonfail=True)

    assert login['success'] is True

    # make sure the session token we used to log in is gone
    # check if our session was deleted correctly
    session_still_exists = actions.auth_session_exists(
        {'session_token': session_token2['session_token']},
        override_authdb_path='sqlite:///test-loginlogout.authdb.sqlite')
    assert session_still_exists['success'] is False

    # start a new session with this user's user ID
    authenticated_session_token = actions.auth_session_new(
        {
            'user_id': login['user_id'],
            'user_agent': 'Mozzarella Killerwhale',
            'expires': datetime.utcnow() + timedelta(hours=1),
            'ip_address': '1.1.1.1',
            'extra_info_json': {
                'pref_datasets_always_private': True
            }
        },
        override_authdb_path='sqlite:///test-loginlogout.authdb.sqlite',
        raiseonfail=True)

    # now see if we can log out
    logged_out = actions.auth_user_logout(
        {
            'session_token': authenticated_session_token['session_token'],
            'user_id': login['user_id']
        },
        override_authdb_path='sqlite:///test-loginlogout.authdb.sqlite',
        raiseonfail=True)

    assert logged_out['success'] is True

    # check if our session was deleted correctly
    session_still_exists = actions.auth_session_exists(
        {'session_token': authenticated_session_token},
        override_authdb_path='sqlite:///test-loginlogout.authdb.sqlite',
        raiseonfail=True)

    assert session_still_exists['success'] is False

    try:
        os.remove('test-loginlogout.authdb.sqlite')
    except Exception as e:
        pass
    try:
        os.remove('test-loginlogout.authdb.sqlite-shm')
    except Exception as e:
        pass
    try:
        os.remove('test-loginlogout.authdb.sqlite-wal')
    except Exception as e:
        pass
Пример #6
0
def test_sessions():
    """
    This tests session token generation, readback, deletion, and expiry.

    """

    try:
        os.remove("test-creation.authdb.sqlite")
    except Exception:
        pass
    try:
        os.remove("test-creation.authdb.sqlite-shm")
    except Exception:
        pass
    try:
        os.remove("test-creation.authdb.sqlite-wal")
    except Exception:
        pass

    get_test_authdb()

    # session token payload
    session_payload = {
        "user_id": 2,
        "user_agent": "Mozzarella Killerwhale",
        "expires": datetime.utcnow() + timedelta(hours=1),
        "ip_address": "1.2.3.4",
        "extra_info_json": {
            "pref_datasets_always_private": True
        },
        "reqid": 1,
        "pii_salt": "super-random-salt",
    }

    # check creation
    session_token1 = actions.auth_session_new(
        session_payload,
        override_authdb_path="sqlite:///test-creation.authdb.sqlite",
    )
    assert session_token1["success"] is True
    assert session_token1["session_token"] is not None

    # check deletion
    deleted = actions.auth_session_delete(
        {
            "session_token": session_token1["session_token"],
            "reqid": 1,
            "pii_salt": "super-random-salt",
        },
        override_authdb_path="sqlite:///test-creation.authdb.sqlite",
    )
    assert deleted["success"] is True

    # check readback of deleted
    check = actions.auth_session_exists(
        {
            "session_token": session_token1["session_token"],
            "reqid": 1,
            "pii_salt": "super-random-salt",
        },
        override_authdb_path="sqlite:///test-creation.authdb.sqlite",
    )
    assert check["success"] is False

    # new session token payload
    session_payload = {
        "user_id": 2,
        "user_agent": "Mozzarella Killerwhale",
        "expires": datetime.utcnow() + timedelta(hours=1),
        "ip_address": "1.2.3.4",
        "extra_info_json": {
            "pref_datasets_always_private": True
        },
        "reqid": 1,
        "pii_salt": "super-random-salt",
    }

    # check creation
    session_token2 = actions.auth_session_new(
        session_payload,
        override_authdb_path="sqlite:///test-creation.authdb.sqlite",
    )
    assert session_token2["success"] is True
    assert session_token2["session_token"] is not None
    assert session_token1["session_token"] != session_token2["session_token"]

    # get items for session_token
    check = actions.auth_session_exists(
        {
            "session_token": session_token2["session_token"],
            "reqid": 1,
            "pii_salt": "super-random-salt",
        },
        override_authdb_path="sqlite:///test-creation.authdb.sqlite",
    )

    assert check["success"] is True

    for key in (
            "user_id",
            "full_name",
            "email",
            "email_verified",
            "emailverify_sent_datetime",
            "is_active",
            "last_login_try",
            "last_login_success",
            "created_on",
            "user_role",
            "session_token",
            "ip_address",
            "user_agent",
            "created",
            "expires",
            "extra_info_json",
    ):
        assert key in check["session_info"]

    assert check["session_info"]["user_id"] == 2
    assert (
        check["session_info"]["full_name"] == "The systemwide anonymous user")
    assert check["session_info"]["email"] == "anonuser@localhost"
    assert check["session_info"]["email_verified"] is True
    assert check["session_info"]["is_active"] is True
    assert check["session_info"]["last_login_try"] is None
    assert check["session_info"]["last_login_success"] is None
    assert check["session_info"]["user_role"] == "anonymous"
    assert (check["session_info"]["session_token"] ==
            session_token2["session_token"])
    assert check["session_info"]["ip_address"] == session_payload["ip_address"]
    assert check["session_info"]["user_agent"] == session_payload["user_agent"]
    assert check["session_info"]["expires"] == session_payload["expires"]
    assert (check["session_info"]["extra_info_json"] ==
            session_payload["extra_info_json"])

    # new session token payload
    session_payload = {
        "user_id": 2,
        "user_agent": "Mozzarella Killerwhale",
        "expires": datetime.utcnow() + timedelta(seconds=5),
        "ip_address": "1.2.3.4",
        "extra_info_json": {
            "pref_datasets_always_private": True
        },
        "reqid": 1,
        "pii_salt": "super-random-salt",
    }

    # check creation
    session_token3 = actions.auth_session_new(
        session_payload,
        override_authdb_path="sqlite:///test-creation.authdb.sqlite",
    )
    assert session_token3["success"] is True
    assert session_token3["session_token"] is not None
    assert session_token3["session_token"] != session_token2["session_token"]

    # check readback when expired
    time.sleep(10.0)

    check = actions.auth_session_exists(
        {
            "session_token": session_token3["session_token"],
            "reqid": 1,
            "pii_salt": "super-random-salt",
        },
        override_authdb_path="sqlite:///test-creation.authdb.sqlite",
    )

    assert check["success"] is False

    try:
        os.remove("test-creation.authdb.sqlite")
    except Exception:
        pass
    try:
        os.remove("test-creation.authdb.sqlite-shm")
    except Exception:
        pass
    try:
        os.remove("test-creation.authdb.sqlite-wal")
    except Exception:
        pass
Пример #7
0
def test_login_timing():
    '''This tests obfuscating the presence/absence of users based on password
    checks.

    This may fail randomly if the testing service is under load.

    '''

    try:
        os.remove('test-timing.authdb.sqlite')
    except Exception as e:
        pass
    try:
        os.remove('test-timing.authdb.sqlite-shm')
    except Exception as e:
        pass
    try:
        os.remove('test-timing.authdb.sqlite-wal')
    except Exception as e:
        pass

    get_test_authdb()

    # create the user
    user_payload = {
        'full_name': 'Test User',
        'email': '*****@*****.**',
        'password': '******'
    }
    user_created = actions.create_new_user(
        user_payload,
        override_authdb_path='sqlite:///test-timing.authdb.sqlite')
    assert user_created['success'] is True
    assert user_created['user_email'] == '*****@*****.**'
    assert ('User account created. Please verify your email address to log in.'
            in user_created['messages'])

    # create a new session token
    session_payload = {
        'user_id': 2,
        'user_agent': 'Mozzarella Killerwhale',
        'expires': datetime.utcnow() + timedelta(hours=1),
        'ip_address': '1.1.1.1',
        'extra_info_json': {
            'pref_datasets_always_private': True
        }
    }

    # check creation of session
    session_token1 = actions.auth_session_new(
        session_payload,
        override_authdb_path='sqlite:///test-timing.authdb.sqlite')
    assert session_token1['success'] is True
    assert session_token1['session_token'] is not None

    # try logging in now with correct password
    login = actions.auth_user_login(
        {
            'session_token': session_token1['session_token'],
            'email': user_payload['email'],
            'password': user_payload['password']
        },
        override_authdb_path='sqlite:///test-timing.authdb.sqlite')

    # this should fail because we haven't verified our email yet
    assert login['success'] is False

    # verify our email
    emailverify = (actions.verify_user_email_address(
        {
            'email': user_payload['email'],
            'user_id': user_created['user_id']
        },
        override_authdb_path='sqlite:///test-timing.authdb.sqlite'))

    assert emailverify['success'] is True
    assert emailverify['user_id'] == user_created['user_id']
    assert emailverify['is_active'] is True
    assert emailverify['user_role'] == 'authenticated'

    # now make a new session token
    session_payload = {
        'user_id': 2,
        'user_agent': 'Mozzarella Killerwhale',
        'expires': datetime.utcnow() + timedelta(hours=1),
        'ip_address': '1.1.1.1',
        'extra_info_json': {
            'pref_datasets_always_private': True
        }
    }

    # check creation of session
    session_token2 = actions.auth_session_new(
        session_payload,
        override_authdb_path='sqlite:///test-timing.authdb.sqlite')
    assert session_token2['success'] is True
    assert session_token2['session_token'] is not None

    # and now try to log in again
    login = actions.auth_user_login(
        {
            'session_token': session_token2['session_token'],
            'email': user_payload['email'],
            'password': user_payload['password']
        },
        override_authdb_path='sqlite:///test-timing.authdb.sqlite')

    assert login['success'] is True

    # basic tests for timing attacks

    # incorrect passwords
    incorrect_timings = []
    for _ in range(1000):

        # now make a new session token
        session_payload = {
            'user_id': 2,
            'user_agent': 'Mozzarella Killerwhale',
            'expires': datetime.utcnow() + timedelta(hours=1),
            'ip_address': '1.1.1.1',
            'extra_info_json': {
                'pref_datasets_always_private': True
            }
        }

        # check creation of session
        session_token2 = actions.auth_session_new(
            session_payload,
            override_authdb_path='sqlite:///test-timing.authdb.sqlite')

        start = time.time()
        actions.auth_user_login(
            {
                'session_token': session_token2['session_token'],
                'email': user_payload['email'],
                'password': secrets.token_urlsafe(16)
            },
            override_authdb_path='sqlite:///test-timing.authdb.sqlite')
        end = time.time()
        incorrect_timings.append(end - start)

    # correct passwords
    correct_timings = []
    for _ in range(1000):

        # now make a new session token
        session_payload = {
            'user_id': 2,
            'user_agent': 'Mozzarella Killerwhale',
            'expires': datetime.utcnow() + timedelta(hours=1),
            'ip_address': '1.1.1.1',
            'extra_info_json': {
                'pref_datasets_always_private': True
            }
        }

        # check creation of session
        session_token2 = actions.auth_session_new(
            session_payload,
            override_authdb_path='sqlite:///test-timing.authdb.sqlite')

        start = time.time()
        actions.auth_user_login(
            {
                'session_token': session_token2['session_token'],
                'email': user_payload['email'],
                'password': user_payload['password']
            },
            override_authdb_path='sqlite:///test-timing.authdb.sqlite')
        end = time.time()
        correct_timings.append(end - start)

    # wronguser passwords
    wronguser_timings = []
    for _ in range(1000):

        # now make a new session token
        session_payload = {
            'user_id': 2,
            'user_agent': 'Mozzarella Killerwhale',
            'expires': datetime.utcnow() + timedelta(hours=1),
            'ip_address': '1.1.1.1',
            'extra_info_json': {
                'pref_datasets_always_private': True
            }
        }

        # check creation of session
        session_token2 = actions.auth_session_new(
            session_payload,
            override_authdb_path='sqlite:///test-timing.authdb.sqlite')

        start = time.time()
        actions.auth_user_login(
            {
                'session_token': session_token2['session_token'],
                'email': secrets.token_urlsafe(16),
                'password': secrets.token_urlsafe(16)
            },
            override_authdb_path='sqlite:///test-timing.authdb.sqlite')
        end = time.time()
        wronguser_timings.append(end - start)

    # broken requests
    broken_timings = []
    for _ in range(1000):

        # now make a new session token
        session_payload = {
            'user_id': 2,
            'user_agent': 'Mozzarella Killerwhale',
            'expires': datetime.utcnow() + timedelta(hours=1),
            'ip_address': '1.1.1.1',
            'extra_info_json': {
                'pref_datasets_always_private': True
            }
        }

        # check creation of session
        session_token2 = actions.auth_session_new(
            session_payload,
            override_authdb_path='sqlite:///test-timing.authdb.sqlite')

        start = time.time()
        actions.auth_user_login(
            {
                'session_token': 'correcthorsebatterystaple',
                'email': user_payload['email'],
                'password': user_payload['password']
            },
            override_authdb_path='sqlite:///test-timing.authdb.sqlite')
        end = time.time()
        broken_timings.append(end - start)

    correct_timings = np.array(correct_timings)
    incorrect_timings = np.array(incorrect_timings)
    broken_timings = np.array(broken_timings)
    wronguser_timings = np.array(wronguser_timings)

    correct_median = np.median(correct_timings)
    incorrect_median = np.median(incorrect_timings)
    broken_median = np.median(broken_timings)
    wronguser_median = np.median(wronguser_timings)

    # all timings should match within 7 milliseconds or so
    assert_allclose(correct_median, incorrect_median, atol=7.0e-3)
    assert_allclose(correct_median, broken_median, atol=7.0e-3)
    assert_allclose(correct_median, wronguser_median, atol=7.0e-3)

    try:
        os.remove('test-timing.authdb.sqlite')
    except Exception as e:
        pass
    try:
        os.remove('test-timing.authdb.sqlite-shm')
    except Exception as e:
        pass
    try:
        os.remove('test-timing.authdb.sqlite-wal')
    except Exception as e:
        pass
Пример #8
0
def test_login():
    '''
    This tests if we can log in successfully or fail correctly.

    '''

    try:
        os.remove('test-login.authdb.sqlite')
    except Exception as e:
        pass
    try:
        os.remove('test-login.authdb.sqlite-shm')
    except Exception as e:
        pass
    try:
        os.remove('test-login.authdb.sqlite-wal')
    except Exception as e:
        pass

    get_test_authdb()

    # create the user
    user_payload = {
        'full_name': 'Test User',
        'email': '*****@*****.**',
        'password': '******'
    }
    user_created = actions.create_new_user(
        user_payload,
        override_authdb_path='sqlite:///test-login.authdb.sqlite')
    assert user_created['success'] is True
    assert user_created['user_email'] == '*****@*****.**'
    assert ('User account created. Please verify your email address to log in.'
            in user_created['messages'])

    # create a new session token
    session_payload = {
        'user_id': 2,
        'user_agent': 'Mozzarella Killerwhale',
        'expires': datetime.utcnow() + timedelta(hours=1),
        'ip_address': '1.1.1.1',
        'extra_info_json': {
            'pref_datasets_always_private': True
        }
    }

    # check creation of session
    session_token1 = actions.auth_session_new(
        session_payload,
        override_authdb_path='sqlite:///test-login.authdb.sqlite')
    assert session_token1['success'] is True
    assert session_token1['session_token'] is not None

    # try logging in now with correct password
    login = actions.auth_user_login(
        {
            'session_token': session_token1['session_token'],
            'email': user_payload['email'],
            'password': user_payload['password']
        },
        override_authdb_path='sqlite:///test-login.authdb.sqlite')

    # this should fail because we haven't verified our email yet
    assert login['success'] is False

    # verify our email
    emailverify = (actions.verify_user_email_address(
        {
            'email': user_payload['email'],
            'user_id': user_created['user_id']
        },
        override_authdb_path='sqlite:///test-login.authdb.sqlite'))

    assert emailverify['success'] is True
    assert emailverify['user_id'] == user_created['user_id']
    assert emailverify['is_active'] is True
    assert emailverify['user_role'] == 'authenticated'

    # now make a new session token
    session_payload = {
        'user_id': emailverify['user_id'],
        'user_agent': 'Mozzarella Killerwhale',
        'expires': datetime.utcnow() + timedelta(hours=1),
        'ip_address': '1.1.1.1',
        'extra_info_json': {
            'pref_datasets_always_private': True
        }
    }

    # check creation of session
    session_token2 = actions.auth_session_new(
        session_payload,
        override_authdb_path='sqlite:///test-login.authdb.sqlite')
    assert session_token2['success'] is True
    assert session_token2['session_token'] is not None

    # and now try to log in again
    login = actions.auth_user_login(
        {
            'session_token': session_token2['session_token'],
            'email': user_payload['email'],
            'password': user_payload['password']
        },
        override_authdb_path='sqlite:///test-login.authdb.sqlite')

    assert login['success'] is True

    # try logging in now with the wrong password
    login = actions.auth_user_login(
        {
            'session_token': session_token2['session_token'],
            'email': user_payload['email'],
            'password': '******'
        },
        override_authdb_path='sqlite:///test-login.authdb.sqlite')
    assert login['success'] is False

    # tests for no session token provided
    login = actions.auth_user_login(
        {
            'session_token': 'correcthorsebatterystaple',
            'email': user_payload['email'],
            'password': user_payload['password']
        },
        override_authdb_path='sqlite:///test-login.authdb.sqlite')
    assert login['success'] is False

    try:
        os.remove('test-login.authdb.sqlite')
    except Exception as e:
        pass
    try:
        os.remove('test-login.authdb.sqlite-shm')
    except Exception as e:
        pass
    try:
        os.remove('test-login.authdb.sqlite-wal')
    except Exception as e:
        pass
Пример #9
0
def test_create_user_with_email(tmpdir):
    """
    This creates a user and tries to send a verification code to their email.

    """

    test_authdb_url = get_test_authdb(tmpdir)
    get_public_suffix_list()

    # 0. start the email server
    email_server, maildir = generate_email_server(tmpdir)
    email_server.start()
    time.sleep(3.0)

    # 1a. create a new session
    session_payload = {
        "user_id": 2,
        "user_agent": "Mozzarella Killerwhale",
        "expires": datetime.utcnow() + timedelta(hours=1),
        "ip_address": "1.1.1.1",
        "extra_info_json": {"pref_datasets_always_private": True},
        "pii_salt": "super-secret-salt",
        "reqid": 1,
    }
    session_token_info = actions.auth_session_new(
        session_payload, raiseonfail=True, override_authdb_path=test_authdb_url
    )

    # 1b. create a new user
    payload = {
        "full_name": "Test User",
        "email": "*****@*****.**",
        "password": "******",
        "reqid": 1,
        "pii_salt": "super-secret-salt",
    }
    user_created = actions.create_new_user(
        payload, raiseonfail=True, override_authdb_path=test_authdb_url
    )
    assert user_created["success"] is True
    assert user_created["user_email"] == "*****@*****.**"
    assert user_created["user_id"] == 4
    assert user_created["send_verification"] is True
    assert (
        "User account created. Please verify your email address to log in."
        in user_created["messages"]
    )

    token_key = Fernet.generate_key()

    # 2. generate a verification token and send them an email
    verify_token = tokens.generate_email_token(
        session_payload["ip_address"],
        session_payload["user_agent"],
        "*****@*****.**",
        session_token_info["session_token"],
        token_key,
    )

    # this uses the payload method of sending SMTP settings to the backend
    # function
    verification_email_info = actions.send_signup_verification_email(
        {
            "email_address": "*****@*****.**",
            "session_token": session_token_info["session_token"],
            "created_info": user_created,
            "server_name": "Authnzerver",
            "server_baseurl": "https://localhost/auth",
            "account_verify_url": "/users/verify",
            "verification_token": verify_token,
            "verification_expiry": 900,
            "emailuser": None,
            "emailpass": None,
            "emailserver": "localhost",
            "emailport": 9487,
            "emailsender": "Authnzerver <*****@*****.**>",
            "reqid": 1337,
            "pii_salt": "super-secret-salt",
        },
        raiseonfail=True,
        override_authdb_path=test_authdb_url,
    )
    assert verification_email_info["success"] is True
    assert verification_email_info["email_address"] == "*****@*****.**"

    # 3. check the mailbox to see if the email was received
    mailbox = Maildir(maildir)

    email_found = False

    for _, message in mailbox.items():

        if "Please verify your account sign up request" in message["Subject"]:

            email_found = True
            assert message["From"] == "Authnzerver <*****@*****.**>"
            assert message["To"] == "*****@*****.**"
            assert (
                "\n".join(textwrap.wrap(verify_token.decode()))
                in message.as_string()
            )
            break

    assert email_found is True

    # now verify that the token from the email contains the same info we
    # provided
    received_token_base64 = re.findall(
        r"enter this code:([\S\n]+)into the account verification",
        message.as_string(),
    )
    received_token_base64 = received_token_base64[0]
    received_token_base64 = received_token_base64.replace("\n", "")
    received_token_valid = tokens.verify_email_token(
        received_token_base64,
        session_payload["ip_address"],
        session_payload["user_agent"],
        session_token_info["session_token"],
        "*****@*****.**",
        token_key,
        match_returned_items=("ipa", "usa", "stk", "ema"),
    )
    assert received_token_valid is True

    # 4. set the user's email address as verified
    email_verified_info = actions.set_user_emailaddr_verified(
        {
            "email": "*****@*****.**",
            "reqid": 123,
            "pii_salt": "super-secret-salt",
        },
        raiseonfail=True,
        override_authdb_path=test_authdb_url,
    )

    assert email_verified_info["success"] is True
    assert email_verified_info["user_id"] == 4
    assert email_verified_info["is_active"] is True
    assert email_verified_info["user_role"] == "authenticated"

    # 5. send a password forgot email to the user

    # 5a. create a new session for the user first
    session_payload = {
        "user_id": 4,
        "user_agent": "Mozzarella Killerwhale",
        "expires": datetime.utcnow() + timedelta(hours=1),
        "ip_address": "1.1.1.1",
        "extra_info_json": {"pref_datasets_always_private": True},
        "pii_salt": "super-secret-salt",
        "reqid": 1,
    }
    session_token_info = actions.auth_session_new(
        session_payload, raiseonfail=True, override_authdb_path=test_authdb_url
    )

    # 5b. now send a forgot-password email
    forgotpass_token = tokens.generate_email_token(
        session_payload["ip_address"],
        session_payload["user_agent"],
        "*****@*****.**",
        session_token_info["session_token"],
        token_key,
    )

    # this uses the config object method of sending SMTP settings to the backend
    # function
    config_obj = SimpleNamespace()
    config_obj.emailuser = None
    config_obj.emailpass = None
    config_obj.emailserver = "localhost"
    config_obj.emailport = 9487
    config_obj.emailsender = "Authnzerver <*****@*****.**>"

    forgotpass_email_info = actions.send_forgotpass_verification_email(
        {
            "email_address": "*****@*****.**",
            "session_token": session_token_info["session_token"],
            "server_name": "Authnzerver",
            "server_baseurl": "https://localhost/auth",
            "password_forgot_url": "/password/reset-step1",
            "verification_token": forgotpass_token,
            "verification_expiry": 900,
            "reqid": 1337,
            "pii_salt": "super-secret-salt",
        },
        raiseonfail=True,
        override_authdb_path=test_authdb_url,
        config=config_obj,
    )
    assert forgotpass_email_info["success"] is True
    assert forgotpass_email_info["email_address"] == "*****@*****.**"

    # 6. check the mailbox to see if the forgot password email was received
    mailbox = Maildir(maildir)

    email_found = False

    for _, message in mailbox.items():

        if "Please verify your password reset request" in message["Subject"]:

            email_found = True
            assert message["From"] == "Authnzerver <*****@*****.**>"
            assert message["To"] == "*****@*****.**"
            assert (
                "\n".join(textwrap.wrap(forgotpass_token.decode()))
                in message.as_string()
            )
            break

    assert email_found is True

    # now verify that the token from the email contains the same info we
    # provided
    received_token_base64 = re.findall(
        r"enter this code:([\S\n]+)into the password reset",
        message.as_string(),
    )
    received_token_base64 = received_token_base64[0]
    received_token_base64 = received_token_base64.replace("\n", "")
    received_token_valid = tokens.verify_email_token(
        received_token_base64,
        session_payload["ip_address"],
        session_payload["user_agent"],
        session_token_info["session_token"],
        "*****@*****.**",
        token_key,
        match_returned_items=("ipa", "usa", "stk", "ema"),
    )
    assert received_token_valid is True

    #
    # clean up
    #

    email_server.stop()