Esempio n. 1
0
    def test_rename_auth_app(self):
        # User has already add an unconfirmed auth app
        old_device_name = "Nokia 3310"
        setup_2fa_totp_device(self.user, old_device_name)
        self.visit(AccountPages.two_factors_authentication_url)  # refresh page

        # User rename existing emergency code
        new_device_name = "My precious yPhone xD"
        self.rename_auth_app(new_name=new_device_name)

        # User see the set name have been updated in the device list
        self.assertNotIn(old_device_name,
                         self.get_elem_text(self.auth_app_divs))
        self.assertIn(new_device_name, self.get_elem_text(self.auth_app_divs))

        # User logout
        self.visit(LoginPage.logout_url)

        # Remove middleware mock, to restore check pages
        self.middleware_patcher.stop()

        # User login again, the 2fa check page appears.
        self.log_user()
        self.wait_for_elem_to_disappear(self.login_submit_input)

        # The new device name is available in the select
        self.assertEqual(new_device_name,
                         self.get_elem_text(self.check_pages_device_input))
Esempio n. 2
0
    def test_add_auth_app_confirmed(self):
        # Make TOTP.time setter set a hard coded secret_time to always be able to confirm app with the same valid_token
        totp_time_setter.side_effect = mocked_totp_time_setter

        # User has already add an unconfirmed auth app
        device_name = "My precious yPhone xD"
        setup_2fa_totp_device(self.user,
                              device_name,
                              secret_key=TOTP_DEVICE_SECRET_KEY,
                              confirmed=False)
        self.visit(AccountPages.two_factors_authentication_url)  # refresh page

        # User resume its totp device setup
        self.get_elem(self.unconfirmed_badges).click()

        # User can see qr code to scan
        self.get_elem(self.qr_code_image)

        # User scan the QR code and input generated code
        self.enter_2fa_code(TOTP_DEVICE_VALID_TOKEN)

        # User is invited to add a emergency code as backup
        self.assertIn("emergency codes",
                      self.get_elem_text(self.device_name_label).lower())

        # User go back to 2fa index page and can see the auth app he just added
        self.get_elem(self.cancel_button).click()
        self.assertIn(device_name, self.get_elem_text(self.auth_app_divs))
        self.assertNotIn(
            "not confirmed",
            self.get_elem_text(self.auth_app_divs).lower(),
            "The totp device should be confirmed",
        )

        # User logout
        self.visit(LoginPage.logout_url)

        # Remove middleware mock, to restore check pages
        self.middleware_patcher.stop()

        # User login again, the 2fa check page appears.
        self.log_user()

        # Check page appears ask for totp
        self.assertIn(
            "authenticator app",
            self.get_elem_text(self.check_pages_device_label).lower(),
        )

        # No alternative 2FA are shown
        with self.assertRaises(NoSuchElementException):
            self.get_elem(self.check_pages_alternatives_list)

        # User can complete login using a valid 2FA code
        self.enter_2fa_code(TOTP_DEVICE_VALID_TOKEN)
        self.assertIn("home", self.head_title)
Esempio n. 3
0
    def test_delete_auth_app_with_emergency_code(self):
        # User has already added an auth app and a emergency codes set
        setup_2fa_totp_device(self.user)
        setup_2fa_static_device(self.user)
        self.visit(AccountPages.two_factors_authentication_url)  # refresh page

        # User delete existing auth app
        self.get_elems(self.delete_auth_app_buttons)[0].click()

        # A warning message appears to inform user 2FA will be completely disable as emergency code are only available
        # when another 2fa device type is set
        self.assertIn("last 2FA device",
                      self.get_elem_text(self.delete_warning))
    def test_user_setup_all_2fa(self):
        # Make TOTP.time setter set a hard coded secret_time to always be able to confirm app with the same valid_token
        totp_time_setter.side_effect = mocked_totp_time_setter

        # User add an auth app (can't be really added in this test)
        setup_2fa_totp_device(self.user, secret_key=TOTP_DEVICE_SECRET_KEY)
        self.visit(AccountPages.two_factors_authentication_url)  # refresh page

        # User add emergency code too
        self.add_emergency_codes_set("My emergency codes")

        # Finally, user add a security key (can't be really added in this test)
        setup_2fa_fido2_device(self.user)
        self.visit(AccountPages.two_factors_authentication_url)  # refresh page

        # The 3 2FA devices appears in the list
        self.assertEqual(1, len(self.get_elems(self.auth_app_divs)))
        self.assertEqual(1, len(self.get_elems(self.emergency_codes_divs)))
        self.assertEqual(1, len(self.get_elems(self.security_key_divs)))

        # User logout and login
        self.visit(LoginPage.logout_url)
        self.middleware_patcher.stop(
        )  # Remove middleware mock, to restore check pages
        self.log_user()

        # The 2FA check page appears with all device available
        self.assertEqual(
            2, len(self.get_elems(self.check_pages_alternatives_list)))

        # Login using totp
        for i, item_text in enumerate(
                self.get_elems_text(self.check_pages_alternatives_list)):
            if "authentication app" in item_text:
                self.get_elems(self.check_pages_alternatives_list)[i].click()
        self.enter_2fa_code(TOTP_DEVICE_VALID_TOKEN)
        self.assertIn("home", self.head_title)

        # user delete its security key 2FA
        self.visit(self.two_factors_authentication_url)
        # User delete existing security key
        self.get_elems(self.delete_security_key_buttons)[0].click()

        # There is no special warning about it, as there is auth app 2fa left
        with self.assertRaises(NoSuchElementException):
            self.get_elem(self.delete_warning)
Esempio n. 5
0
    def test_add_auth_app_with_wrong_confirmation_code(self):
        # Make TOTP.time setter set a hard coded secret_time to always be able to confirm app with the same valid_token
        totp_time_setter.side_effect = mocked_totp_time_setter
        setup_2fa_static_device(self.user)  # emergency code already set

        # User has already add an unconfirmed auth app and resume its totp device setup
        device_name = "My precious yPhone xD"
        setup_2fa_totp_device(self.user,
                              device_name,
                              secret_key=TOTP_DEVICE_SECRET_KEY,
                              confirmed=False)
        self.visit(AccountPages.two_factors_authentication_url)  # refresh page
        self.get_elem(self.unconfirmed_badges).click()

        # User enter invalid code
        self.enter_2fa_code(TOTP_DEVICE_INVALID_TOKEN)

        # An error message appears
        self.get_elem(self.error_message)
Esempio n. 6
0
    def test_add_auth_app_with_emergency_code_already_set(self):
        # Make TOTP.time setter set a hard coded secret_time to always be able to confirm app with the same valid_token
        totp_time_setter.side_effect = mocked_totp_time_setter
        setup_2fa_static_device(self.user)  # emergency code already set

        # User has already add an unconfirmed auth app and resume its totp device setup
        device_name = "My precious yPhone xD"
        setup_2fa_totp_device(self.user,
                              device_name,
                              secret_key=TOTP_DEVICE_SECRET_KEY,
                              confirmed=False)
        self.visit(AccountPages.two_factors_authentication_url)  # refresh page
        self.get_elem(self.unconfirmed_badges).click()

        # User scan the QR code and input generated code
        self.enter_2fa_code(TOTP_DEVICE_VALID_TOKEN)

        # User has already a "emergency codes set" set, so he get redirected to 2FA devices list
        self.wait_for_elem_to_show(self.auth_app_divs)
Esempio n. 7
0
    def test_otp_list_returns_correct_html(self):
        # Make TOTP.time setter set a hard coded secret_time to always be able to confirm app with the same valid_token
        totp_time_setter.side_effect = mocked_totp_time_setter

        # Given no 2fa devices are setup
        response = self.client.get("/accounts/2fa/")
        self.assertContains(response, "Protect your Paper Matter account")
        self.assertTemplateUsed(response, "otp_ftl/device_list.html")

        # Given 2fa devices are setup
        setup_2fa_static_device(self.user,
                                codes_list=tv.STATIC_DEVICE_CODES_LIST)
        setup_2fa_fido2_device(self.user)
        setup_2fa_totp_device(self.user)

        response = self.client.get("/accounts/2fa/")
        self.assertContains(response, "Emergency codes")
        self.assertContains(response, "Security keys (U2F/FIDO2)")
        self.assertContains(response, "Authenticator apps")
Esempio n. 8
0
 def setUp(self):
     self.org_1 = setup_org()
     self.org_2 = setup_org(name=tv.ORG_NAME_2, slug=tv.ORG_SLUG_2)
     self.user_1 = setup_user(org=self.org_1)
     self.user_2 = setup_user(org=self.org_1,
                              email=tv.USER2_EMAIL,
                              password=tv.USER2_PASS)
     self.user_1_codes_1 = ["AA1222", "AA1223"]
     self.user_1_static_device_1 = setup_2fa_static_device(
         self.user_1,
         "user1 valid token set 1",
         codes_list=self.user_1_codes_1)
     self.user_1_fido2_device_1 = setup_2fa_fido2_device(
         self.user_1, "user1 fido2 device 1")
     self.user_1_totp_device_1 = setup_2fa_totp_device(
         self.user_1, "user1 totp 1")
     self.user_1_totp_device_2 = setup_2fa_totp_device(
         self.user_1, "user1 totp 2")
     self.user_2_totp_device_2 = setup_2fa_totp_device(
         self.user_2, "user2 totp 1")
Esempio n. 9
0
    def test_delete_auth_app(self):
        # User has already added an auth app
        setup_2fa_totp_device(self.user)
        self.visit(AccountPages.two_factors_authentication_url)  # refresh page

        # User delete existing auth app
        self.delete_auth_app()

        # User see the set have been remove from the device list
        with self.assertRaises(NoSuchElementException):
            self.get_elem(self.auth_app_divs)

        # User logout
        self.visit(LoginPage.logout_url)

        # Remove middleware mock, to restore check pages
        self.middleware_patcher.stop()

        # When user login again there is no 2FA check page as there is no 2fa devices set
        self.log_user()
        self.assertIn("home", self.head_title)
Esempio n. 10
0
    def test_otp_list_context(self):
        # Make TOTP.time setter set a hard coded secret_time to always be able to confirm app with the same valid_token
        totp_time_setter.side_effect = mocked_totp_time_setter

        # Given 2fa devices are setup
        static_device_1 = setup_2fa_static_device(
            self.user, "SD1", codes_list=tv.STATIC_DEVICE_CODES_LIST)
        static_device_2 = setup_2fa_static_device(
            self.user, "SD2", codes_list=tv.STATIC_DEVICE_CODES_LIST)
        totp_device_1 = setup_2fa_totp_device(self.user, "TD1")
        totp_device_2 = setup_2fa_totp_device(self.user, "TD2")
        fido2_device_1 = setup_2fa_fido2_device(self.user, "FD1")
        fido2_device_2 = setup_2fa_fido2_device(self.user, "FD2")

        response = self.client.get("/accounts/2fa/")

        self.assertCountEqual(response.context["static_devices"],
                              [static_device_1, static_device_2])
        self.assertCountEqual(response.context["totp_devices"],
                              [totp_device_1, totp_device_2])
        self.assertCountEqual(response.context["fido2_devices"],
                              [fido2_device_1, fido2_device_2])
Esempio n. 11
0
 def setUp(self):
     # Setup org, user, a totp device and the user is logged
     self.org = setup_org()
     self.user = setup_user(self.org)
     self.totp_device = setup_2fa_totp_device(self.user, confirmed=False)
     setup_authenticated_session(self.client, self.org, self.user)
     # mock OTPMiddleware._verify_user() to skip check page
     self.middleware_patcher = patch.object(OTPMiddleware, "_verify_user",
                                            mocked_verify_user)
     self.middleware_patcher.start()
     self.addCleanup(
         patch.stopall
     )  # ensure mock is remove after each test, even if the test crash
     self.addCleanup(totp_time_setter.reset_mock, side_effect=True)
Esempio n. 12
0
    def test_otp_static_check_context(self):
        response = self.client.get("/accounts/2fa/static/check/")

        self.assertEqual(response.context["have_static"], True)
        self.assertEqual(response.context["have_fido2"], False)
        self.assertEqual(response.context["have_totp"], False)

        # given user setup static + fido2 devices
        setup_2fa_fido2_device(self.user)

        response = self.client.get("/accounts/2fa/static/check/")

        self.assertEqual(response.context["have_static"], True)
        self.assertEqual(response.context["have_fido2"], True)
        self.assertEqual(response.context["have_totp"], False)
        # given user setup static + fido2 + totp devices
        setup_2fa_totp_device(self.user)

        response = self.client.get("/accounts/2fa/static/check/")

        self.assertEqual(response.context["have_static"], True)
        self.assertEqual(response.context["have_fido2"], True)
        self.assertEqual(response.context["have_totp"], True)
Esempio n. 13
0
    def test_form_save_proper_model(self, random_hex_mock):
        random_hex_mock.return_value = tv.TOTP_DEVICE_SECRET_KEY
        expected_model = setup_2fa_totp_device(
            self.user_1,
            tv.TOTP_DEVICE_NAME,
            secret_key=tv.TOTP_DEVICE_SECRET_KEY)
        form = TOTPDeviceForm(data={"name": tv.TOTP_DEVICE_NAME})

        self.assertTrue(form.is_valid())

        saved_model = form.save(self.user_1)

        self.assertEqual(expected_model.name, saved_model.name)
        self.assertEqual(expected_model.key, saved_model.key)
Esempio n. 14
0
    def test_otp_fido2_check_context(self):
        response = self.client.get("/accounts/2fa/fido2/check/")

        self.assertEqual(response.context["have_fido2"], True)
        self.assertEqual(response.context["have_totp"], False)
        self.assertEqual(response.context["have_static"], False)

        # given user setup totp + fido2 devices
        setup_2fa_totp_device(self.user)

        response = self.client.get("/accounts/2fa/fido2/check/")

        self.assertEqual(response.context["have_fido2"], True)
        self.assertEqual(response.context["have_totp"], True)
        self.assertEqual(response.context["have_static"], False)
        # given user setup static + fido2 + totp devices
        setup_2fa_static_device(self.user,
                                codes_list=tv.STATIC_DEVICE_CODES_LIST)

        response = self.client.get("/accounts/2fa/fido2/check/")

        self.assertEqual(response.context["have_fido2"], True)
        self.assertEqual(response.context["have_totp"], True)
        self.assertEqual(response.context["have_static"], True)
Esempio n. 15
0
    def test_otp_check_redirect_to_proper_view(self):
        # Given no 2fa devices are setup
        response = self.client.get("/app/")
        # Home page is displayed
        self.assertTemplateUsed(response, "core/home.html")

        # Given a static device is setup
        setup_2fa_static_device(self.user,
                                codes_list=tv.STATIC_DEVICE_CODES_LIST)
        response = self.client.get("/app/", follow=True)
        # User is redirect to otp_static_check
        self.assertRedirects(response, reverse_lazy("otp_static_check"))

        # Given static + totp device are setup
        setup_2fa_totp_device(self.user)
        response = self.client.get("/app/", follow=True)
        # User is redirect to otp_static_check
        self.assertRedirects(response, reverse_lazy("otp_totp_check"))

        # Given static + totp + 2fa device are setup
        setup_2fa_fido2_device(self.user)
        response = self.client.get("/app/", follow=True)
        # User is redirect to otp_static_check
        self.assertRedirects(response, reverse_lazy("otp_fido2_check"))
Esempio n. 16
0
    def setUp(self, **kwargs):
        # first org, admin, user, first 2fa device are already created, user is already logged on 2FA account page
        super().setUp()
        self.org = setup_org()
        setup_admin(self.org)
        self.user = setup_user(self.org)
        self.visit(LoginPage.url)
        self.log_user()
        # setup the first device to access emergency codes feature
        self.required_totp_device = setup_2fa_totp_device(self.user)
        # mock OTPMiddleware._verify_user() to skip check page
        self.middleware_patcher = patch.object(OTPMiddleware, "_verify_user",
                                               mocked_verify_user)
        self.middleware_patcher.start()
        self.addCleanup(
            patch.stopall
        )  # ensure mock is remove after each test, even if the test crash

        self.visit(AccountPages.two_factors_authentication_url)
Esempio n. 17
0
    def test_otp_static_delete_context(self):
        response = self.client.get(
            f"/accounts/2fa/totp/{self.totp_device.id}/delete/")

        self.assertEqual(response.context["last_otp"], True)

        # given user add a totp device
        totp_device_2 = setup_2fa_totp_device(self.user)

        response = self.client.get(
            f"/accounts/2fa/totp/{self.totp_device.id}/delete/")

        self.assertEqual(response.context["last_otp"], False)

        # given delete second totp device and add a fido2 device
        totp_device_2.delete()
        setup_2fa_fido2_device(self.user)

        response = self.client.get(
            f"/accounts/2fa/totp/{self.totp_device.id}/delete/")

        self.assertEqual(response.context["last_otp"], False)
Esempio n. 18
0
    def test_session_timeout_reduced_during_2fa_check(self):
        totp_device = setup_2fa_totp_device(self.user,
                                            secret_key=TOTP_DEVICE_SECRET_KEY)
        totp_time_setter.side_effect = mocked_totp_time_setter

        self.client.get("/app/", follow=True)

        # During 2fa session duration must be less than 10 mins
        now = datetime.now(timezone.utc)
        cookie_expiration_time = self.client.cookies["sessionid"]["expires"]
        cookie_expiration_time = datetime.strptime(
            cookie_expiration_time, "%a, %d %b %Y %H:%M:%S GMT")
        cookie_expiration_time = django_timezone.make_aware(
            cookie_expiration_time, timezone.utc)
        delta = cookie_expiration_time - now
        self.assertLessEqual(delta, timedelta(minutes=10))

        self.client.post(
            "/accounts/2fa/totp/check/",
            {
                "otp_device": totp_device.persistent_id,
                "otp_token": TOTP_DEVICE_VALID_TOKEN,
            },
            follow=True,
        )

        # After 2FA check session have to be restore to default value
        cookie_expiration_time = self.client.cookies["sessionid"]["expires"]
        cookie_expiration_time = datetime.strptime(
            cookie_expiration_time, "%a, %d %b %Y %H:%M:%S GMT")
        cookie_expiration_time = django_timezone.make_aware(
            cookie_expiration_time, timezone.utc)
        delta = cookie_expiration_time - now

        self.assertAlmostEqual(round(delta.total_seconds()),
                               settings.SESSION_COOKIE_AGE,
                               delta=5)
Esempio n. 19
0
 def setUp(self):
     self.org_1 = setup_org()
     self.user_1 = setup_user(org=self.org_1)
     self.user_1_totp_device_1 = setup_2fa_totp_device(self.user_1,
                                                       "user1 totp 1",
                                                       confirmed=False)
    def setUp(self, **kwargs):
        # orgs, admin, users are already created
        super().setUp()
        self.admin_org = setup_org(name="admin-org", slug="admin-org")
        self.admin = setup_admin(self.admin_org)
        self.user1_org = setup_org(name=tv.ORG_NAME_1, slug=tv.ORG_SLUG_1)
        self.user1 = setup_user(self.user1_org,
                                email=tv.USER1_EMAIL,
                                password=tv.USER1_PASS)
        self.user2_org = setup_org(name=tv.ORG_NAME_2, slug=tv.ORG_SLUG_2)
        self.user2 = setup_user(self.user2_org,
                                email=tv.USER2_EMAIL,
                                password=tv.USER2_PASS)

        # mock OTPMiddleware._verify_user() to skip check page
        self.middleware_patcher = patch.object(OTPMiddleware, "_verify_user",
                                               mocked_verify_user)
        self.middleware_patcher.start()
        self.addCleanup(
            patch.stopall
        )  # ensure mock is remove after each test, even if the test crash
        self.addCleanup(totp_time_setter.reset_mock, side_effect=True)

        # admin, user1 and user2 have added documents, folders, otp devices
        self.admin_resources = {}
        self.admin_resources["folder1"] = setup_folder(self.admin_org)
        self.admin_resources["sub_folder1"] = setup_folder(
            self.admin_org, parent=self.admin_resources["folder1"])
        self.admin_resources["doc1"] = setup_document(
            self.admin_org,
            ftl_user=self.admin,
            binary=setup_temporary_file().name)
        self.admin_resources["doc2"] = setup_document(
            self.admin_org,
            ftl_user=self.admin,
            ftl_folder=self.admin_resources["folder1"],
            binary=setup_temporary_file().name,
        )
        self.admin_resources["doc3"] = setup_document(
            self.admin_org,
            ftl_user=self.admin,
            ftl_folder=self.admin_resources["sub_folder1"],
            binary=setup_temporary_file().name,
        )
        self.admin_resources["totp_device"] = setup_2fa_totp_device(
            self.admin, secret_key=TOTP_DEVICE_SECRET_KEY)
        self.admin_resources["fido2_device"] = setup_2fa_fido2_device(
            self.admin)
        self.admin_resources["static_device"] = setup_2fa_static_device(
            self.admin, codes_list=["AAA"])

        self.user1_resources = {}
        self.user1_resources["folder1"] = setup_folder(self.user1_org)
        self.user1_resources["sub_folder1"] = setup_folder(
            self.user1_org, parent=self.user1_resources["folder1"])
        self.user1_resources["doc1"] = setup_document(
            self.user1_org,
            ftl_user=self.user1,
            binary=setup_temporary_file().name)
        self.user1_resources["doc2"] = setup_document(
            self.user1_org,
            ftl_user=self.user1,
            ftl_folder=self.user1_resources["folder1"],
            binary=setup_temporary_file().name,
        )
        self.user1_resources["doc3"] = setup_document(
            self.user1_org,
            ftl_user=self.user1,
            ftl_folder=self.user1_resources["sub_folder1"],
            binary=setup_temporary_file().name,
        )
        self.user1_resources["totp_device"] = setup_2fa_totp_device(
            self.user1, secret_key=TOTP_DEVICE_SECRET_KEY)
        self.user1_resources["fido2_device"] = setup_2fa_fido2_device(
            self.user1)
        self.user1_resources["static_device"] = setup_2fa_static_device(
            self.user1, codes_list=["AAA"])

        self.user2_resources = {}
        self.user2_resources["folder1"] = setup_folder(self.user2_org)
        self.user2_resources["sub_folder1"] = setup_folder(
            self.user2_org, parent=self.user2_resources["folder1"])
        self.user2_resources["doc1"] = setup_document(self.user2_org,
                                                      ftl_user=self.user2)
        self.user2_resources["doc2"] = setup_document(
            self.user2_org,
            ftl_user=self.user2,
            ftl_folder=self.user2_resources["folder1"],
        )
        self.user2_resources["doc3"] = setup_document(
            self.user2_org,
            ftl_user=self.user2,
            ftl_folder=self.user2_resources["sub_folder1"],
        )
        self.user2_resources["totp_device"] = setup_2fa_totp_device(
            self.user2, secret_key=TOTP_DEVICE_SECRET_KEY)
        self.user2_resources["fido2_device"] = setup_2fa_fido2_device(
            self.user2)
        self.user2_resources["static_device"] = setup_2fa_static_device(
            self.user2, codes_list=["AAA"])