Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens Langhammer 2023-09-21 18:55:27 +02:00
parent 00fb77e3da
commit 5adbae40ea
No known key found for this signature in database
3 changed files with 14 additions and 12 deletions

View File

@ -24,7 +24,7 @@ from firebase_admin.messaging import (
from rest_framework.serializers import BaseSerializer, Serializer from rest_framework.serializers import BaseSerializer, Serializer
from structlog.stdlib import get_logger from structlog.stdlib import get_logger
from authentik.core.models import ExpiringModel from authentik.core.models import ExpiringModel, User
from authentik.core.types import UserSettingSerializer from authentik.core.types import UserSettingSerializer
from authentik.flows.models import ConfigurableStage, FriendlyNamedStage, Stage from authentik.flows.models import ConfigurableStage, FriendlyNamedStage, Stage
from authentik.lib.generators import generate_id from authentik.lib.generators import generate_id
@ -112,9 +112,9 @@ class MobileDevice(SerializerModel, Device):
class TransactionStates(models.TextChoices): class TransactionStates(models.TextChoices):
"""States a transaction can be in""" """States a transaction can be in"""
wait = "wait" WAIT = "wait"
accept = "accept" ACCEPT = "accept"
deny = "deny" DENY = "deny"
class MobileTransaction(ExpiringModel): class MobileTransaction(ExpiringModel):
@ -123,7 +123,7 @@ class MobileTransaction(ExpiringModel):
tx_id = models.UUIDField(default=uuid4, primary_key=True) tx_id = models.UUIDField(default=uuid4, primary_key=True)
device = models.ForeignKey(MobileDevice, on_delete=models.CASCADE) device = models.ForeignKey(MobileDevice, on_delete=models.CASCADE)
status = models.TextField(choices=TransactionStates.choices, default=TransactionStates.wait) status = models.TextField(choices=TransactionStates.choices, default=TransactionStates.WAIT)
def send_message(self, request: Optional[HttpRequest], **context): def send_message(self, request: Optional[HttpRequest], **context):
"""Send mobile message""" """Send mobile message"""
@ -133,13 +133,14 @@ class MobileTransaction(ExpiringModel):
if request: if request:
branding = request.tenant.branding_title branding = request.tenant.branding_title
domain = request.get_host() domain = request.get_host()
user: User = self.device.user
message = Message( message = Message(
notification=Notification( notification=Notification(
title=__("%(brand)s authentication request" % {"brand": branding}), title=__("%(brand)s authentication request" % {"brand": branding}),
body=__( body=__(
"%(user)s is attempting to log in to %(domain)s" "%(user)s is attempting to log in to %(domain)s"
% { % {
"user": self.device.user.username, "user": user.username, # pylint: disable=no-member
"domain": domain, "domain": domain,
} }
), ),
@ -175,7 +176,7 @@ class MobileTransaction(ExpiringModel):
checks = 0 checks = 0
while True: while True:
self.refresh_from_db() self.refresh_from_db()
if self.status in [TransactionStates.accept, TransactionStates.deny]: if self.status in [TransactionStates.ACCEPT, TransactionStates.DENY]:
self.delete() self.delete()
return self.status return self.status
checks += 1 checks += 1

View File

@ -12,7 +12,7 @@ from authentik.flows.challenge import (
from authentik.flows.stage import ChallengeStageView from authentik.flows.stage import ChallengeStageView
from authentik.stages.authenticator_mobile.models import MobileDevice, MobileDeviceToken from authentik.stages.authenticator_mobile.models import MobileDevice, MobileDeviceToken
FLOW_PLAN_MOBILE_ENROLL_TOKEN = "authentik/stages/authenticator_mobile/enroll/token" FLOW_PLAN_MOBILE_ENROLL_TOKEN = "authentik/stages/authenticator_mobile/enroll/token" # nosec
FLOW_PLAN_MOBILE_ENROLL_DEVICE = "authentik/stages/authenticator_mobile/enroll/device" FLOW_PLAN_MOBILE_ENROLL_DEVICE = "authentik/stages/authenticator_mobile/enroll/device"

View File

@ -182,6 +182,7 @@ def validate_challenge_webauthn(data: dict, stage_view: StageView, user: User) -
def validate_challenge_mobile(device_pk: str, stage_view: StageView, user: User) -> Device: def validate_challenge_mobile(device_pk: str, stage_view: StageView, user: User) -> Device:
"""Validate mobile authenticator"""
device: MobileDevice = get_object_or_404(MobileDevice, pk=device_pk) device: MobileDevice = get_object_or_404(MobileDevice, pk=device_pk)
if device.user != user: if device.user != user:
LOGGER.warning("device mismatch") LOGGER.warning("device mismatch")
@ -197,10 +198,10 @@ def validate_challenge_mobile(device_pk: str, stage_view: StageView, user: User)
).name ).name
try: try:
tx = MobileTransaction.objects.create(device=device) transaction = MobileTransaction.objects.create(device=device)
tx.send_message(stage_view.request, **push_context) transaction.send_message(stage_view.request, **push_context)
status = tx.wait_for_response() status = transaction.wait_for_response()
if status == TransactionStates.deny: if status == TransactionStates.DENY:
LOGGER.debug("mobile push response", result=status) LOGGER.debug("mobile push response", result=status)
login_failed.send( login_failed.send(
sender=__name__, sender=__name__,