def test_user_settings_otp_check_description_escaping(client, dummy_user_with_otp, logged_in_dummy_user, cleanup_dummy_tokens): """Test that we escape the token description when constructing the OTP URI""" current_otp = get_otp(otp_secret_from_uri(dummy_user_with_otp.uri)) result = client.post( "/user/dummy/settings/otp/", data={ "description": "pants token", "password": f"dummy_password{current_otp}" }, follow_redirects=True, ) page = BeautifulSoup(result.data, "html.parser") otp_uri = page.select_one("input#otp-uri") parsed_otp_uri = urlparse(otp_uri["value"]) parsed_query = parse_qs(parsed_otp_uri.query) # Not sure we need all of these checked assert parsed_otp_uri.scheme == "otpauth" assert parsed_otp_uri.netloc == "totp" assert parsed_otp_uri.path == "/[email protected]:pants%20token" assert parsed_query["issuer"] == ["*****@*****.**"]
def test_change_post_with_otp(client, dummy_user, dummy_user_with_otp, token_for_dummy_user, patched_lock_active): otp = get_otp(otp_secret_from_uri(dummy_user_with_otp.uri)) with fml_testing.mock_sends( UserUpdateV1({ "msg": { "agent": "dummy", "user": "******", "fields": ["password"] } })): result = client.post( f'/forgot-password/change?token={token_for_dummy_user}', data={ "password": "******", "password_confirm": "newpassword", "otp": otp, }, ) patched_lock_active["delete"].assert_called() assert_redirects_with_flash( result, expected_url="/", expected_message="Your password has been changed.", expected_category="success", )
def test_user_settings_otp_add_second(client, logged_in_dummy_user_with_otp, cleanup_dummy_tokens): """Test posting to the create OTP endpoint""" otp = get_otp(otp_secret_from_uri(logged_in_dummy_user_with_otp.uri)) result = client.post( "/user/dummy/settings/otp/", data={ "add-description": "pants token 2", "add-password": "******", "add-otp": otp, "add-submit": "1", }, ) page = BeautifulSoup(result.data, "html.parser") tokenlist = page.select_one("div.list-group") assert tokenlist is not None tokens = tokenlist.select( ".list-group-item div[data-role='token-description']") assert len(tokens) == 1 modal = page.select_one("#otp-modal") assert modal is not None confirm_form = modal.select_one("form") assert confirm_form is not None assert (confirm_form.select_one("input[name='confirm-description']") ["value"] == "pants token 2") otp_uri = page.select_one("input#otp-uri") parsed_otp_uri_query = parse_qs(urlparse(otp_uri["value"]).query) assert (confirm_form.select_one("input[name='confirm-secret']")["value"] == parsed_otp_uri_query["secret"][0])
def test_change_post_with_otp( client, dummy_user, dummy_user_with_otp, token_for_dummy_user, patched_lock_active ): otp = get_otp(otp_secret_from_uri(dummy_user_with_otp.uri)) result = client.post( f'/forgot-password/change?token={token_for_dummy_user}', data={"password": "******", "password_confirm": "newpassword", "otp": otp}, ) patched_lock_active["delete"].assert_called() assert_redirects_with_flash( result, expected_url="/", expected_message="Your password has been changed.", expected_category="success", )
def test_user_settings_otp_add_second( client, dummy_user_with_otp, logged_in_dummy_user, cleanup_dummy_tokens ): """Test posting to the create OTP endpoint""" current_otp = get_otp(otp_secret_from_uri(dummy_user_with_otp.uri)) result = client.post( "/user/dummy/settings/otp/", data={"description": "pants token", "password": f"dummy_password{current_otp}"}, follow_redirects=True, ) page = BeautifulSoup(result.data, "html.parser") tokenlist = page.select_one("div.list-group") assert tokenlist is not None # check we are showing 2 tokens tokens = tokenlist.select(".list-group-item .h6 div[data-role='token-description']") assert len(tokens) == 2 # check the 2nd token is in the list assert tokens[1].get_text(strip=True) == "pants token" # check the modal is on the page assert len(page.select("#otp-modal")) == 1
def test_login_with_otp(client, dummy_user_with_otp): """Test a successful Login with password + otp""" otp = get_otp(otp_secret_from_uri(dummy_user_with_otp.uri)) result = client.post( '/', data={ "login-username": "******", "login-password": "******", "login-otp": otp, "login-submit": "1", }, follow_redirects=False, ) assert_redirects_with_flash( result, expected_url="/user/dummy/", expected_message="Welcome, dummy!", expected_category="success", ) assert session.get("noggin_username") == "dummy" assert session.get("noggin_session") is not None
def test_user_settings_otp_check_no_description( client, dummy_user_with_otp, logged_in_dummy_user, cleanup_dummy_tokens ): """Test an OTP token without a description""" current_otp = get_otp(otp_secret_from_uri(dummy_user_with_otp.uri)) result = client.post( "/user/dummy/settings/otp/", data={"password": f"dummy_password{current_otp}"}, follow_redirects=True, ) page = BeautifulSoup(result.data, "html.parser") tokenlist = page.select_one("div.list-group") assert tokenlist is not None tokens = tokenlist.select(".list-group-item .h6 div[data-role='token-description']") assert len(tokens) == 2 assert tokens[0].get_text(strip=True) == "" assert tokens[1].get_text(strip=True) == "dummy's token"
def test_user_settings_otp_check_description_escaping(client, dummy_user_with_otp, logged_in_dummy_user, cleanup_dummy_tokens): """Test that we escape the token description when constructing the OTP URI""" current_otp = get_otp(otp_secret_from_uri(dummy_user_with_otp.uri)) result = client.post( "/user/dummy/settings/otp/", data={ "description": "pants token", "password": f"dummy_password{current_otp}" }, follow_redirects=True, ) page = BeautifulSoup(result.data, "html.parser") otp_uri = page.select_one("input#otp-uri") assert ( otp_uri['value'] == "otpauth://totp/[email protected]:pants%20token?issuer=" "dummy%40EXAMPLE.COM&secret=L4PD6EXABBJDSCAKS6MZQWT4RSP3PM3QW6H57UHIKFCN7I3" "FGKSHZCCO&digits=6&algorithm=SHA512&period=30")