test_twofactor.py 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. from time import time
  2. from unittest import mock
  3. from sentry.auth.authenticators.totp import TotpInterface
  4. from sentry.testutils.cases import TestCase
  5. from sentry.testutils.silo import control_silo_test
  6. @control_silo_test(stable=True)
  7. class TwoFactorTest(TestCase):
  8. def test_not_pending_2fa(self):
  9. resp = self.client.get("/auth/2fa/")
  10. assert resp.status_code == 302
  11. assert resp["Location"] == "/auth/login/"
  12. def test_no_2fa_configured(self):
  13. user = self.create_user()
  14. self.login_as(user)
  15. self.session["_pending_2fa"] = [user.id, time() - 2]
  16. self.save_session()
  17. resp = self.client.get("/auth/2fa/", follow=True)
  18. assert resp.redirect_chain == [
  19. ("/auth/login/", 302),
  20. ("/organizations/new/", 302),
  21. ]
  22. def test_otp_challenge(self):
  23. user = self.create_user()
  24. interface = TotpInterface()
  25. interface.enroll(user)
  26. self.login_as(user)
  27. self.session["_pending_2fa"] = [user.id, time() - 2]
  28. self.save_session()
  29. resp = self.client.get("/auth/2fa/")
  30. assert resp.status_code == 200
  31. self.assertTemplateUsed("sentry/twofactor.html")
  32. assert "provide the access code" in resp.content.decode("utf8")
  33. @mock.patch("sentry.auth.authenticators.TotpInterface.validate_otp", return_value=None)
  34. @mock.patch("time.sleep")
  35. def test_otp_submit_error(self, mock_sleep, mock_validate):
  36. user = self.create_user()
  37. interface = TotpInterface()
  38. interface.enroll(user)
  39. self.login_as(user)
  40. self.session["_pending_2fa"] = [user.id, time() - 2]
  41. self.save_session()
  42. resp = self.client.post("/auth/2fa/", data={"otp": "123456"}, follow=True)
  43. assert mock_validate.called
  44. assert resp.status_code == 200
  45. assert "Invalid confirmation code" in resp.content.decode("utf8")
  46. @mock.patch("sentry.auth.authenticators.TotpInterface.validate_otp", return_value=True)
  47. def test_otp_submit_success(self, mock_validate):
  48. user = self.create_user()
  49. interface = TotpInterface()
  50. interface.enroll(user)
  51. self.login_as(user)
  52. self.session["_pending_2fa"] = [user.id, time() - 2]
  53. self.save_session()
  54. resp = self.client.post("/auth/2fa/", data={"otp": "123456"}, follow=True)
  55. assert mock_validate.called
  56. assert resp.redirect_chain == [
  57. ("/auth/login/", 302),
  58. ("/organizations/new/", 302),
  59. ]