예제 #1
0
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"] == ["*****@*****.**"]
예제 #2
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))
    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",
    )
예제 #3
0
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])
예제 #4
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",
    )
예제 #5
0
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
예제 #6
0
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
예제 #7
0
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"
예제 #8
0
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")