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
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
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 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
def test_create_user(): ''' This runs through various iterations of creating a user. ''' 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() # 1. dumb password payload = { 'full_name': 'Test User', 'email': '*****@*****.**', 'password': '******' } user_created = actions.create_new_user( payload, override_authdb_path='sqlite:///test-creation.authdb.sqlite') assert user_created['success'] is False assert user_created['user_email'] == '*****@*****.**' assert user_created['user_id'] is None assert user_created['send_verification'] is False assert ('Your password is too short. It must have at least 12 characters.' in user_created['messages']) assert ('Your password is too similar to either ' 'the domain name of this server or your ' 'own name or email address.' in user_created['messages']) assert ('Your password is not complex enough. ' 'One or more characters appear appear too frequently.' in user_created['messages']) assert ('Your password is on the list of the most common ' 'passwords and is vulnerable to guessing.' in user_created['messages']) # 2. all numeric password payload = { 'full_name': 'Test User', 'email': '*****@*****.**', 'password': '******' } user_created = actions.create_new_user( payload, override_authdb_path='sqlite:///test-creation.authdb.sqlite') assert user_created['success'] is False assert user_created['user_email'] == '*****@*****.**' assert user_created['user_id'] is None assert user_created['send_verification'] is False assert ('Your password cannot be all numbers.' in user_created['messages']) # 3a. password ~= email address payload = { 'full_name': 'Test User', 'email': '*****@*****.**', 'password': '******' } user_created = actions.create_new_user( payload, override_authdb_path='sqlite:///test-creation.authdb.sqlite') assert user_created['success'] is False assert user_created['user_email'] == '*****@*****.**' assert user_created['user_id'] is None assert user_created['send_verification'] is False assert ('Your password is not complex enough. ' 'One or more characters appear appear too frequently.' in user_created['messages']) assert ('Your password is too similar to either ' 'the domain name of this server or your ' 'own name or email address.' in user_created['messages']) # 3b. password ~= full name payload = { 'full_name': 'Test User', 'email': '*****@*****.**', 'password': '******' } user_created = actions.create_new_user( payload, override_authdb_path='sqlite:///test-creation.authdb.sqlite') assert user_created['success'] is False assert user_created['user_email'] == '*****@*****.**' assert user_created['user_id'] is None assert user_created['send_verification'] is False assert ('Your password is too similar to either ' 'the domain name of this server or your ' 'own name or email address.' in user_created['messages']) # 4. password is OK payload = { 'full_name': 'Test User', 'email': '*****@*****.**', 'password': '******' } user_created = actions.create_new_user( payload, override_authdb_path='sqlite:///test-creation.authdb.sqlite') 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']) # 5. try to create a new user with an existing email address payload = { 'full_name': 'Test User', 'email': '*****@*****.**', 'password': '******' } user_created = actions.create_new_user( payload, override_authdb_path='sqlite:///test-creation.authdb.sqlite') assert user_created['success'] is False assert user_created['user_email'] == '*****@*****.**' assert user_created['user_id'] == 4 # we should not send a verification email because the user already has an # account or if the account is not active yet, the last verification email # was sent less than 24 hours ago assert user_created['send_verification'] is False assert ('User account created. Please verify your email address to log in.' in user_created['messages']) 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
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
def test_create_user(): """ This runs through various iterations of creating a user. """ 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() suff_list = get_public_suffix_list() # 0a. full name spam with no http:// payload = { "full_name": "Test User bIt.Ly/hahaspam", "email": "*****@*****.**", "password": "******", "reqid": 1, "pii_salt": "super-random-salt", "public_suffix_list": suff_list, } user_created = actions.create_new_user( payload, override_authdb_path="sqlite:///test-creation.authdb.sqlite") assert user_created["success"] is False assert user_created["user_email"] is None assert user_created["user_id"] is None assert user_created["send_verification"] is False assert user_created["failure_reason"] == "invalid full name" # 0b. full name spam with http:// payload = { "full_name": "Test User HttPs://BIT.lY/hahaspam", "email": "*****@*****.**", "password": "******", "reqid": 1, "pii_salt": "super-random-salt", "public_suffix_list": suff_list, } user_created = actions.create_new_user( payload, override_authdb_path="sqlite:///test-creation.authdb.sqlite") assert user_created["success"] is False assert user_created["user_email"] is None assert user_created["user_id"] is None assert user_created["send_verification"] is False assert user_created["failure_reason"] == "invalid full name" # 0c. full name spam with http:// and checking if currproc works OK payload = { "full_name": "Test User HttPs://BIT.lY/hahaspam", "email": "*****@*****.**", "password": "******", "reqid": 1, "pii_salt": "super-random-salt", } user_created = actions.create_new_user( payload, override_authdb_path="sqlite:///test-creation.authdb.sqlite") assert user_created["success"] is False assert user_created["user_email"] is None assert user_created["user_id"] is None assert user_created["send_verification"] is False assert user_created["failure_reason"] == "invalid full name" # 1. dumb password payload = { "full_name": "Test User", "email": "*****@*****.**", "password": "******", "reqid": 1, "pii_salt": "super-random-salt", "public_suffix_list": suff_list, } user_created = actions.create_new_user( payload, override_authdb_path="sqlite:///test-creation.authdb.sqlite") assert user_created["success"] is False assert user_created["user_email"] == "*****@*****.**" assert user_created["user_id"] is None assert user_created["send_verification"] is False assert ("Your password is too short. It must have at least 12 characters." in user_created["messages"]) assert ("Your password is too similar to either " "the domain name of this server or your " "own name or email address." in user_created["messages"]) assert ("Your password is on the list of the most common " "passwords and is vulnerable to guessing." in user_created["messages"]) # 1a. 'clever'-dumb password payload = { "full_name": "Test User", "email": "*****@*****.**", "password": "******", "reqid": 1, "pii_salt": "super-random-salt", } user_created = actions.create_new_user( payload, override_authdb_path="sqlite:///test-creation.authdb.sqlite") assert user_created["success"] is False assert user_created["user_email"] == "*****@*****.**" assert user_created["user_id"] is None assert user_created["send_verification"] is False msg_found = False for msg in user_created["messages"]: if "recently compromised Web account passwords from" in msg: msg_found = True break assert msg_found, f"Pwned message not in {user_created['messages']}" # 2. all numeric password payload = { "full_name": "Test User", "email": "*****@*****.**", "password": "******", "reqid": 1, "pii_salt": "super-random-salt", "public_suffix_list": suff_list, } user_created = actions.create_new_user( payload, override_authdb_path="sqlite:///test-creation.authdb.sqlite") assert user_created["success"] is False assert user_created["user_email"] == "*****@*****.**" assert user_created["user_id"] is None assert user_created["send_verification"] is False assert "Your password cannot be all numbers." in user_created["messages"] # 3a. password ~= email address payload = { "full_name": "Test User", "email": "*****@*****.**", "password": "******", "reqid": 1, "pii_salt": "super-random-salt", } user_created = actions.create_new_user( payload, override_authdb_path="sqlite:///test-creation.authdb.sqlite") assert user_created["success"] is False assert user_created["user_email"] == "*****@*****.**" assert user_created["user_id"] is None assert user_created["send_verification"] is False assert ("Your password is too similar to either " "the domain name of this server or your " "own name or email address." in user_created["messages"]) # 3b. password ~= full name payload = { "full_name": "Test User", "email": "*****@*****.**", "password": "******", "reqid": 1, "pii_salt": "super-random-salt", "public_suffix_list": suff_list, } user_created = actions.create_new_user( payload, override_authdb_path="sqlite:///test-creation.authdb.sqlite") assert user_created["success"] is False assert user_created["user_email"] == "*****@*****.**" assert user_created["user_id"] is None assert user_created["send_verification"] is False assert ("Your password is too similar to either " "the domain name of this server or your " "own name or email address." in user_created["messages"]) # 4. password is OK payload = { "full_name": "Test User", "email": "*****@*****.**", "password": "******", "system_id": "totally-random-systemid-1234", "reqid": 1, "pii_salt": "super-random-salt", } user_created = actions.create_new_user( payload, override_authdb_path="sqlite:///test-creation.authdb.sqlite") assert user_created["success"] is True assert user_created["user_email"] == "*****@*****.**" assert user_created["user_id"] == 4 assert user_created["system_id"] == "totally-random-systemid-1234" assert user_created["send_verification"] is True assert ("User account created. Please verify your email address to log in." in user_created["messages"]) # 5. try to create a new user with an existing email address payload = { "full_name": "Test User", "email": "*****@*****.**", "password": "******", "reqid": 1, "pii_salt": "super-random-salt", "public_suffix_list": suff_list, } user_created = actions.create_new_user( payload, override_authdb_path="sqlite:///test-creation.authdb.sqlite") assert user_created["success"] is False assert user_created["user_email"] == "*****@*****.**" assert user_created["user_id"] == 4 # we should not send a verification email because the user already has an # account or if the account is not active yet, the last verification email # was sent less than 24 hours ago assert user_created["send_verification"] is False assert ("User account created. Please verify your email address to log in." in user_created["messages"]) 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
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()
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
def test_issue_apikey(tmpdir): """ Test if issuing an API key works. """ delete_test_authdb(tmpdir) test_authdb_url = get_test_authdb(tmpdir) teardown() get_public_suffix_list() # 1. 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 # 2. verify their email email_verified_info = actions.set_user_emailaddr_verified( { "email": "*****@*****.**", "reqid": 2, "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" # 3. generate an API key apikey_issue_payload = { "issuer": "authnzerver", "audience": "test-service", "subject": "/test-endpoint", "apiversion": 1, "expires_seconds": 7, "not_valid_before": 1, "user_id": 4, "user_role": "authenticated", "ip_address": "1.2.3.4", "refresh_expires": 10, "refresh_nbf": 2, "reqid": 3, "pii_salt": "super-secret-salt", } apikey_info = actions.issue_apikey_nosession( apikey_issue_payload, raiseonfail=True, override_authdb_path=test_authdb_url, override_permissions_json=permissions_json, ) assert apikey_info["success"] is True for key in ("apikey", "expires", "refresh_token", "refresh_token_expires"): assert key in apikey_info apikey = json.loads(apikey_info["apikey"]) assert apikey["ipa"] == apikey_issue_payload["ip_address"] assert apikey["uid"] == apikey_issue_payload["user_id"] assert apikey["rol"] == apikey_issue_payload["user_role"] teardown()
def test_refresh_apikey(tmpdir): """ This tests refreshing an API key. - before it expires - after it expires - with an unexpired correct refresh token - with the incorrect refresh token - with an expired refresh token """ delete_test_authdb(tmpdir) test_authdb_url = get_test_authdb(tmpdir) teardown() get_public_suffix_list() # 1. 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 # 2. verify their email email_verified_info = actions.set_user_emailaddr_verified( { "email": "*****@*****.**", "reqid": 2, "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" # 3. generate an API key apikey_issue_payload = { "issuer": "authnzerver", "audience": "test-service", "subject": "/test-endpoint", "apiversion": 1, "expires_seconds": 6, "not_valid_before": 1, "user_id": 4, "user_role": "authenticated", "ip_address": "1.2.3.4", "refresh_expires": 10, "refresh_nbf": 1, "reqid": 3, "pii_salt": "super-secret-salt", } apikey_info = actions.issue_apikey_nosession( apikey_issue_payload, raiseonfail=True, override_authdb_path=test_authdb_url, override_permissions_json=permissions_json, ) assert apikey_info["success"] is True for key in ("apikey", "expires", "refresh_token", "refresh_token_expires"): assert key in apikey_info apikey = json.loads(apikey_info["apikey"]) assert apikey["ipa"] == apikey_issue_payload["ip_address"] assert apikey["uid"] == apikey_issue_payload["user_id"] assert apikey["rol"] == apikey_issue_payload["user_role"] # 4. refresh the key immediately - this should fail because of refresh_nbf apikey_refresh_payload = { "apikey_dict": apikey, "user_id": 4, "user_role": "authenticated", "refresh_token": apikey_info["refresh_token"], "ip_address": "1.2.3.4", "expires_seconds": 4, "not_valid_before": 1, "refresh_expires": 10, "refresh_nbf": 1, "reqid": 3, "pii_salt": "super-secret-salt", } refreshed_apikey = actions.refresh_apikey_nosession( apikey_refresh_payload, raiseonfail=True, override_authdb_path=test_authdb_url, override_permissions_json=permissions_json, ) assert refreshed_apikey["success"] is False # 5. now try to refresh within the lifetime of the key but with incorrect # refresh token - should fail time.sleep(2) apikey_refresh_payload["refresh_token"] = "haha wrong token" refreshed_apikey = actions.refresh_apikey_nosession( apikey_refresh_payload, raiseonfail=True, override_authdb_path=test_authdb_url, override_permissions_json=permissions_json, ) assert refreshed_apikey["success"] is False # 6. now try to refresh with correct refresh token - should pass apikey_refresh_payload["refresh_token"] = apikey_info["refresh_token"] refreshed_apikey = actions.refresh_apikey_nosession( apikey_refresh_payload, raiseonfail=True, override_authdb_path=test_authdb_url, override_permissions_json=permissions_json, ) assert refreshed_apikey["success"] is True # 7. now try to refresh after the key expires - should pass time.sleep(6) refreshed_apikey_dict = json.loads(refreshed_apikey["apikey"]) apikey_refresh_payload = { "apikey_dict": refreshed_apikey_dict, "user_id": 4, "user_role": "authenticated", "refresh_token": refreshed_apikey["refresh_token"], "ip_address": "1.2.3.4", "expires_seconds": 4, "not_valid_before": 1, "refresh_expires": 5, "refresh_nbf": 1, "reqid": 3, "pii_salt": "super-secret-salt", } refreshed_apikey = actions.refresh_apikey_nosession( apikey_refresh_payload, raiseonfail=True, override_authdb_path=test_authdb_url, override_permissions_json=permissions_json, ) assert refreshed_apikey["success"] is True # 8. now try to refresh after the refresh token expires - should fail time.sleep(6) refreshed_apikey = actions.refresh_apikey_nosession( apikey_refresh_payload, raiseonfail=True, override_authdb_path=test_authdb_url, override_permissions_json=permissions_json, ) assert refreshed_apikey["success"] is False teardown()
def test_revoke_all_apikeys(tmpdir): """ This tests if all API keys for a user can be revoked. """ delete_test_authdb(tmpdir) test_authdb_url = get_test_authdb(tmpdir) teardown() get_public_suffix_list() # 1. 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 # 2. verify their email email_verified_info = actions.set_user_emailaddr_verified( { "email": "*****@*****.**", "reqid": 2, "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" # 3. generate a couple of API keys apikey_payload_one = { "issuer": "authnzerver", "audience": "test-service", "subject": "/test-endpoint-one", "apiversion": 1, "expires_seconds": 7, "not_valid_before": 1, "user_id": 4, "user_role": "authenticated", "ip_address": "1.2.3.4", "refresh_expires": 10, "refresh_nbf": 2, "reqid": 3, "pii_salt": "super-secret-salt", } apikey_info_one = actions.issue_apikey_nosession( apikey_payload_one, raiseonfail=True, override_authdb_path=test_authdb_url, override_permissions_json=permissions_json, ) apikey_one = json.loads(apikey_info_one["apikey"]) apikey_payload_two = { "issuer": "authnzerver", "audience": "test-service", "subject": "/test-endpoint-two", "apiversion": 1, "expires_seconds": 7, "not_valid_before": 1, "user_id": 4, "user_role": "authenticated", "ip_address": "1.2.3.4", "refresh_expires": 10, "refresh_nbf": 2, "reqid": 3, "pii_salt": "super-secret-salt", } apikey_info_two = actions.issue_apikey_nosession( apikey_payload_two, raiseonfail=True, override_authdb_path=test_authdb_url, override_permissions_json=permissions_json, ) apikey_two = json.loads(apikey_info_two["apikey"]) time.sleep(2) # 1. try to revoke all API keys with an incorrect API key good_tkn = apikey_one["tkn"] apikey_one["tkn"] = "haha-bad-token" revoke_one = actions.revoke_all_apikeys_nosession( { "apikey_dict": apikey_one, "user_id": 4, "user_role": "authenticated", "reqid": 2, "pii_salt": "super-secret-salt", }, raiseonfail=True, override_authdb_path=test_authdb_url, override_permissions_json=permissions_json, ) assert revoke_one["success"] is False # 2. try to revoke all API keys with a correct API key revoke_two = actions.revoke_all_apikeys_nosession( { "apikey_dict": apikey_two, "user_id": 4, "user_role": "authenticated", "reqid": 2, "pii_salt": "super-secret-salt", }, raiseonfail=True, override_authdb_path=test_authdb_url, override_permissions_json=permissions_json, ) assert revoke_two["success"] is True # 3. make sure we can't use any API key afterwards apikey_one["tkn"] = good_tkn verify_one = actions.verify_apikey_nosession( { "apikey_dict": apikey_one, "user_id": 4, "user_role": "authenticated", "reqid": 3, "pii_salt": "super-secret-salt", }, raiseonfail=True, override_authdb_path=test_authdb_url, override_permissions_json=permissions_json, ) assert verify_one["success"] is False verify_two = actions.verify_apikey_nosession( { "apikey_dict": apikey_two, "user_id": 4, "user_role": "authenticated", "reqid": 4, "pii_salt": "super-secret-salt", }, raiseonfail=True, override_authdb_path=test_authdb_url, override_permissions_json=permissions_json, ) assert verify_two["success"] is False teardown()
def test_revoke_apikey(tmpdir): """ This tests if an apikey can be revoked. - by the original user - by another user who somehow gets the API key """ delete_test_authdb(tmpdir) test_authdb_url = get_test_authdb(tmpdir) teardown() get_public_suffix_list() # 1. create a couple of new users 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 payload = { "full_name": "Another Test User", "email": "*****@*****.**", "password": "******", "reqid": 2, "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"] == 5 # 2. verify their emails email_verified_info = actions.set_user_emailaddr_verified( { "email": "*****@*****.**", "reqid": 3, "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" email_verified_info = actions.set_user_emailaddr_verified( { "email": "*****@*****.**", "reqid": 4, "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"] == 5 assert email_verified_info["is_active"] is True assert email_verified_info["user_role"] == "authenticated" # 3. generate an API key for the first user apikey_issue_payload = { "issuer": "authnzerver", "audience": "test-service", "subject": "/test-endpoint", "apiversion": 1, "expires_seconds": 6, "not_valid_before": 2, "user_id": 4, "user_role": "authenticated", "ip_address": "1.2.3.4", "refresh_expires": 10, "refresh_nbf": 2, "reqid": 5, "pii_salt": "super-secret-salt", } apikey_info = actions.issue_apikey_nosession( apikey_issue_payload, raiseonfail=True, override_authdb_path=test_authdb_url, override_permissions_json=permissions_json, ) assert apikey_info["success"] is True apikey_dict = json.loads(apikey_info["apikey"]) time.sleep(2) # 4. try to revoke the API key as a different user # this should fail apikey_revocation = actions.revoke_apikey_nosession( { "apikey_dict": apikey_dict, "user_id": 5, "user_role": "authenticated", "reqid": 6, "pii_salt": "super-secret-salt", }, raiseonfail=True, override_authdb_path=test_authdb_url, override_permissions_json=permissions_json, ) assert apikey_revocation["success"] is False # 5. try to revoke the API key as the correct user # this should pass apikey_revocation = actions.revoke_apikey_nosession( { "apikey_dict": apikey_dict, "user_id": 4, "user_role": "authenticated", "reqid": 7, "pii_salt": "super-secret-salt", }, raiseonfail=True, override_authdb_path=test_authdb_url, override_permissions_json=permissions_json, ) assert apikey_revocation["success"] is True # 6. try to verify the API key after it has been revoked # this should fail apikey_verification = actions.verify_apikey_nosession( { "apikey_dict": apikey_dict, "user_id": 4, "user_role": "authenticated", "reqid": 8, "pii_salt": "super-secret-salt", }, raiseonfail=True, override_authdb_path=test_authdb_url, override_permissions_json=permissions_json, ) assert apikey_verification["success"] is False # 7. try to verify the API key as a different user - this should fail anyway apikey_verification = actions.verify_apikey_nosession( { "apikey_dict": apikey_dict, "user_id": 5, "user_role": "authenticated", "reqid": 9, "pii_salt": "super-secret-salt", }, raiseonfail=True, override_authdb_path=test_authdb_url, override_permissions_json=permissions_json, ) assert apikey_verification["success"] is False teardown()
def test_verify_apikey(tmpdir): """ This tests if the issued API key can be verified: - within expiry time - within expiry but with other user - after expiry time """ delete_test_authdb(tmpdir) test_authdb_url = get_test_authdb(tmpdir) teardown() get_public_suffix_list() # 1. create a couple of new users 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 payload = { "full_name": "Another Test User", "email": "*****@*****.**", "password": "******", "reqid": 2, "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"] == 5 # 2. verify their emails email_verified_info = actions.set_user_emailaddr_verified( { "email": "*****@*****.**", "reqid": 3, "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" email_verified_info = actions.set_user_emailaddr_verified( { "email": "*****@*****.**", "reqid": 4, "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"] == 5 assert email_verified_info["is_active"] is True assert email_verified_info["user_role"] == "authenticated" # 3. generate an API key for the first user apikey_issue_payload = { "issuer": "authnzerver", "audience": "test-service", "subject": "/test-endpoint", "apiversion": 1, "expires_seconds": 6, "not_valid_before": 2, "user_id": 4, "user_role": "authenticated", "ip_address": "1.2.3.4", "refresh_expires": 10, "refresh_nbf": 2, "reqid": 4, "pii_salt": "super-secret-salt", } apikey_info = actions.issue_apikey_nosession( apikey_issue_payload, raiseonfail=True, override_authdb_path=test_authdb_url, override_permissions_json=permissions_json, ) assert apikey_info["success"] is True apikey_dict = json.loads(apikey_info["apikey"]) # 4. try to verify the API key immediately - should fail because of # not-before apikey_verification = actions.verify_apikey_nosession( { "apikey_dict": apikey_dict, "user_id": 4, "user_role": "authenticated", "reqid": 5, "pii_salt": "super-secret-salt", }, raiseonfail=True, override_authdb_path=test_authdb_url, override_permissions_json=permissions_json, ) assert apikey_verification["success"] is False # 5. wait 3 seconds, then verify again - this should pass time.sleep(3) apikey_verification = actions.verify_apikey_nosession( { "apikey_dict": apikey_dict, "user_id": 4, "user_role": "authenticated", "reqid": 6, "pii_salt": "super-secret-salt", }, raiseonfail=True, override_authdb_path=test_authdb_url, override_permissions_json=permissions_json, ) assert apikey_verification["success"] is True # 6. try to verify the API key as a different user - this should fail apikey_verification = actions.verify_apikey_nosession( { "apikey_dict": apikey_dict, "user_id": 5, "user_role": "authenticated", "reqid": 6, "pii_salt": "super-secret-salt", }, raiseonfail=True, override_authdb_path=test_authdb_url, override_permissions_json=permissions_json, ) assert apikey_verification["success"] is False # 7. wait 6 seconds, then try to reverify the API key as the original user # it should have expired by now so this should fail time.sleep(6) apikey_verification = actions.verify_apikey_nosession( { "apikey_dict": apikey_dict, "user_id": 4, "user_role": "authenticated", "reqid": 7, "pii_salt": "super-secret-salt", }, raiseonfail=True, override_authdb_path=test_authdb_url, ) assert apikey_verification["success"] is False teardown()