diff --git a/authentik/stages/authenticator_static/api.py b/authentik/stages/authenticator_static/api.py index 9ccd4c576..f2d639e14 100644 --- a/authentik/stages/authenticator_static/api.py +++ b/authentik/stages/authenticator_static/api.py @@ -61,7 +61,7 @@ class StaticDeviceViewSet( ): """Viewset for static authenticator devices""" - queryset = StaticDevice.objects.all() + queryset = StaticDevice.objects.filter(confirmed=True) serializer_class = StaticDeviceSerializer permission_classes = [OwnerPermissions] filter_backends = [OwnerFilter, DjangoFilterBackend, OrderingFilter, SearchFilter] diff --git a/authentik/stages/authenticator_static/stage.py b/authentik/stages/authenticator_static/stage.py index b9d7a44c1..13056de9e 100644 --- a/authentik/stages/authenticator_static/stage.py +++ b/authentik/stages/authenticator_static/stage.py @@ -55,7 +55,7 @@ class AuthenticatorStaticStageView(ChallengeStageView): stage: AuthenticatorStaticStage = self.executor.current_stage if SESSION_STATIC_DEVICE not in self.request.session: - device = StaticDevice(user=user, confirmed=True, name="Static Token") + device = StaticDevice(user=user, confirmed=False, name="Static Token") tokens = [] for _ in range(0, stage.token_count): tokens.append(StaticToken(device=device, token=StaticToken.random_token())) @@ -66,6 +66,7 @@ class AuthenticatorStaticStageView(ChallengeStageView): def challenge_valid(self, response: ChallengeResponse) -> HttpResponse: """Verify OTP Token""" device: StaticDevice = self.request.session[SESSION_STATIC_DEVICE] + device.confirmed = True device.save() for token in self.request.session[SESSION_STATIC_TOKENS]: token.save() diff --git a/authentik/stages/authenticator_totp/api.py b/authentik/stages/authenticator_totp/api.py index 9e9d2d27f..dd651bb5b 100644 --- a/authentik/stages/authenticator_totp/api.py +++ b/authentik/stages/authenticator_totp/api.py @@ -54,7 +54,7 @@ class TOTPDeviceViewSet( ): """Viewset for totp authenticator devices""" - queryset = TOTPDevice.objects.all() + queryset = TOTPDevice.objects.filter(confirmed=True) serializer_class = TOTPDeviceSerializer permission_classes = [OwnerPermissions] filter_backends = [OwnerFilter, DjangoFilterBackend, OrderingFilter, SearchFilter] diff --git a/authentik/stages/authenticator_totp/stage.py b/authentik/stages/authenticator_totp/stage.py index 733064774..4c6250b87 100644 --- a/authentik/stages/authenticator_totp/stage.py +++ b/authentik/stages/authenticator_totp/stage.py @@ -42,6 +42,7 @@ class AuthenticatorTOTPChallengeResponse(ChallengeResponse): """Validate totp code""" if self.device is not None: if not self.device.verify_token(code): + self.device.confirmed = False raise ValidationError(_("Code does not match")) return code @@ -82,7 +83,7 @@ class AuthenticatorTOTPStageView(ChallengeStageView): if SESSION_TOTP_DEVICE not in self.request.session: device = TOTPDevice( - user=user, confirmed=True, digits=stage.digits, name="TOTP Authenticator" + user=user, confirmed=False, digits=stage.digits, name="TOTP Authenticator" ) self.request.session[SESSION_TOTP_DEVICE] = device @@ -91,6 +92,7 @@ class AuthenticatorTOTPStageView(ChallengeStageView): def challenge_valid(self, response: ChallengeResponse) -> HttpResponse: """TOTP Token is validated by challenge""" device: TOTPDevice = self.request.session[SESSION_TOTP_DEVICE] + device.confirmed = True device.save() del self.request.session[SESSION_TOTP_DEVICE] return self.executor.stage_ok()