stages/authenticator_totp: remove single device per user limit
closes #3281 Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
ade2d4879c
commit
2a42c203b2
|
@ -74,14 +74,6 @@ class AuthenticatorTOTPStageView(ChallengeStageView):
|
|||
|
||||
stage: AuthenticatorTOTPStage = self.executor.current_stage
|
||||
|
||||
devices = TOTPDevice.objects.filter(user=user)
|
||||
# Currently, this stage only supports one device per user. If the user already
|
||||
# has a device, just skip to the next stage
|
||||
if devices.exists():
|
||||
if not any(x.confirmed for x in devices):
|
||||
return super().get(request, *args, **kwargs)
|
||||
return self.executor.stage_ok()
|
||||
|
||||
TOTPDevice.objects.create(
|
||||
user=user, confirmed=False, digits=stage.digits, name="TOTP Authenticator"
|
||||
)
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
"""Test validator stage"""
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from django.contrib.sessions.middleware import SessionMiddleware
|
||||
from django.test.client import RequestFactory
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
from authentik.core.tests.utils import create_test_admin_user
|
||||
from authentik.flows.planner import FlowPlan
|
||||
from authentik.flows.stage import StageView
|
||||
from authentik.flows.tests import FlowTestCase
|
||||
from authentik.flows.views.executor import FlowExecutorView
|
||||
from authentik.lib.generators import generate_id, generate_key
|
||||
from authentik.lib.tests.utils import dummy_get_response
|
||||
from authentik.stages.authenticator_duo.models import AuthenticatorDuoStage, DuoDevice
|
||||
from authentik.stages.authenticator_validate.challenge import validate_challenge_duo
|
||||
from authentik.tenants.utils import get_tenant_for_request
|
||||
|
||||
|
||||
class AuthenticatorValidateStageDuoTests(FlowTestCase):
|
||||
|
@ -23,6 +27,12 @@ class AuthenticatorValidateStageDuoTests(FlowTestCase):
|
|||
def test_device_challenge_duo(self):
|
||||
"""Test duo"""
|
||||
request = self.request_factory.get("/")
|
||||
|
||||
middleware = SessionMiddleware(dummy_get_response)
|
||||
middleware.process_request(request)
|
||||
request.session.save()
|
||||
setattr(request, "tenant", get_tenant_for_request(request))
|
||||
|
||||
stage = AuthenticatorDuoStage.objects.create(
|
||||
name=generate_id(),
|
||||
client_id=generate_id(),
|
||||
|
@ -33,7 +43,9 @@ class AuthenticatorValidateStageDuoTests(FlowTestCase):
|
|||
user=self.user,
|
||||
stage=stage,
|
||||
)
|
||||
duo_mock = MagicMock(
|
||||
with patch(
|
||||
"authentik.stages.authenticator_duo.models.AuthenticatorDuoStage.client",
|
||||
MagicMock(
|
||||
auth=MagicMock(
|
||||
return_value={
|
||||
"result": "allow",
|
||||
|
@ -41,27 +53,35 @@ class AuthenticatorValidateStageDuoTests(FlowTestCase):
|
|||
"status_msg": "Success. Logging you in...",
|
||||
}
|
||||
)
|
||||
)
|
||||
failed_duo_mock = MagicMock(auth=MagicMock(return_value={"result": "deny"}))
|
||||
with patch(
|
||||
"authentik.stages.authenticator_duo.models.AuthenticatorDuoStage.client",
|
||||
duo_mock,
|
||||
),
|
||||
):
|
||||
self.assertEqual(
|
||||
duo_device,
|
||||
validate_challenge_duo(
|
||||
duo_device.pk,
|
||||
StageView(FlowExecutorView(current_stage=stage), request=request),
|
||||
StageView(
|
||||
FlowExecutorView(
|
||||
current_stage=stage,
|
||||
plan=FlowPlan(generate_id(), [], {}),
|
||||
),
|
||||
request=request,
|
||||
),
|
||||
self.user,
|
||||
),
|
||||
)
|
||||
with patch(
|
||||
"authentik.stages.authenticator_duo.models.AuthenticatorDuoStage.client",
|
||||
failed_duo_mock,
|
||||
MagicMock(auth=MagicMock(return_value={"result": "deny"})),
|
||||
):
|
||||
with self.assertRaises(ValidationError):
|
||||
validate_challenge_duo(
|
||||
duo_device.pk,
|
||||
StageView(FlowExecutorView(current_stage=stage), request=request),
|
||||
StageView(
|
||||
FlowExecutorView(
|
||||
current_stage=stage,
|
||||
plan=FlowPlan(generate_id(), [], {}),
|
||||
),
|
||||
request=request,
|
||||
),
|
||||
self.user,
|
||||
)
|
||||
|
|
Reference in New Issue