authentik.stages.authenticator_validate.models
Authenticator Validation Stage
1"""Authenticator Validation Stage""" 2 3from django.contrib.postgres.fields.array import ArrayField 4from django.db import models 5from django.utils.translation import gettext_lazy as _ 6from django.views import View 7from rest_framework.serializers import BaseSerializer 8 9from authentik.flows.models import NotConfiguredAction, Stage 10from authentik.lib.utils.time import timedelta_string_validator 11from authentik.stages.authenticator_webauthn.models import UserVerification, WebAuthnHint 12 13 14class DeviceClasses(models.TextChoices): 15 """Device classes this stage can validate""" 16 17 # device class must match Device's class name so StaticDevice -> static 18 STATIC = "static", _("Static") 19 TOTP = "totp", _("TOTP") 20 WEBAUTHN = "webauthn", _("WebAuthn") 21 DUO = "duo", _("Duo") 22 SMS = "sms", _("SMS") 23 EMAIL = "email", _("Email") 24 25 @staticmethod 26 def from_model_label(model_label: str) -> DeviceClasses: 27 return getattr( 28 DeviceClasses, model_label.rsplit(".", maxsplit=1)[-1][: -len("device")].upper() 29 ) 30 31 32def default_device_classes() -> list: 33 """By default, accept all device classes""" 34 return [ 35 DeviceClasses.STATIC, 36 DeviceClasses.TOTP, 37 DeviceClasses.WEBAUTHN, 38 DeviceClasses.DUO, 39 DeviceClasses.SMS, 40 DeviceClasses.EMAIL, 41 ] 42 43 44class AuthenticatorValidateStage(Stage): 45 """Validate user's configured Multi Factor Authentication.""" 46 47 not_configured_action = models.TextField( 48 choices=NotConfiguredAction.choices, default=NotConfiguredAction.SKIP 49 ) 50 51 configuration_stages = models.ManyToManyField( 52 Stage, 53 blank=True, 54 default=None, 55 related_name="+", 56 help_text=_( 57 "Stages used to configure Authenticator when user doesn't have any compatible " 58 "devices. After this configuration Stage passes, the user is not prompted again." 59 ), 60 ) 61 62 device_classes = ArrayField( 63 models.TextField(choices=DeviceClasses.choices), 64 help_text=_("Device classes which can be used to authenticate"), 65 default=default_device_classes, 66 ) 67 68 last_auth_threshold = models.TextField( 69 default="seconds=0", 70 validators=[timedelta_string_validator], 71 help_text=_( 72 "If any of the user's device has been used within this threshold, this " 73 "stage will be skipped" 74 ), 75 ) 76 77 webauthn_user_verification = models.TextField( 78 help_text=_("Enforce user verification for WebAuthn devices."), 79 choices=UserVerification.choices, 80 default=UserVerification.PREFERRED, 81 ) 82 webauthn_hints = ArrayField( 83 models.TextField(choices=WebAuthnHint.choices), 84 default=list, 85 blank=True, 86 ) 87 webauthn_allowed_device_types = models.ManyToManyField( 88 "authentik_stages_authenticator_webauthn.WebAuthnDeviceType", blank=True 89 ) 90 91 email_otp_throttling_factor = models.FloatField(default=1) 92 sms_otp_throttling_factor = models.FloatField(default=1) 93 totp_otp_throttling_factor = models.FloatField(default=1) 94 static_otp_throttling_factor = models.FloatField(default=1) 95 96 @property 97 def serializer(self) -> type[BaseSerializer]: 98 from authentik.stages.authenticator_validate.api import AuthenticatorValidateStageSerializer 99 100 return AuthenticatorValidateStageSerializer 101 102 @property 103 def view(self) -> type[View]: 104 from authentik.stages.authenticator_validate.stage import AuthenticatorValidateStageView 105 106 return AuthenticatorValidateStageView 107 108 @property 109 def component(self) -> str: 110 return "ak-stage-authenticator-validate-form" 111 112 def get_throttling_factor(self, device_class: DeviceClasses) -> float | None: 113 if device_class == DeviceClasses.EMAIL: 114 return self.email_otp_throttling_factor 115 elif device_class == DeviceClasses.SMS: 116 return self.sms_otp_throttling_factor 117 elif device_class == DeviceClasses.TOTP: 118 return self.totp_otp_throttling_factor 119 elif device_class == DeviceClasses.STATIC: 120 return self.static_otp_throttling_factor 121 return None 122 123 class Meta: 124 verbose_name = _("Authenticator Validation Stage") 125 verbose_name_plural = _("Authenticator Validation Stages")
15class DeviceClasses(models.TextChoices): 16 """Device classes this stage can validate""" 17 18 # device class must match Device's class name so StaticDevice -> static 19 STATIC = "static", _("Static") 20 TOTP = "totp", _("TOTP") 21 WEBAUTHN = "webauthn", _("WebAuthn") 22 DUO = "duo", _("Duo") 23 SMS = "sms", _("SMS") 24 EMAIL = "email", _("Email") 25 26 @staticmethod 27 def from_model_label(model_label: str) -> DeviceClasses: 28 return getattr( 29 DeviceClasses, model_label.rsplit(".", maxsplit=1)[-1][: -len("device")].upper() 30 )
Device classes this stage can validate
33def default_device_classes() -> list: 34 """By default, accept all device classes""" 35 return [ 36 DeviceClasses.STATIC, 37 DeviceClasses.TOTP, 38 DeviceClasses.WEBAUTHN, 39 DeviceClasses.DUO, 40 DeviceClasses.SMS, 41 DeviceClasses.EMAIL, 42 ]
By default, accept all device classes
45class AuthenticatorValidateStage(Stage): 46 """Validate user's configured Multi Factor Authentication.""" 47 48 not_configured_action = models.TextField( 49 choices=NotConfiguredAction.choices, default=NotConfiguredAction.SKIP 50 ) 51 52 configuration_stages = models.ManyToManyField( 53 Stage, 54 blank=True, 55 default=None, 56 related_name="+", 57 help_text=_( 58 "Stages used to configure Authenticator when user doesn't have any compatible " 59 "devices. After this configuration Stage passes, the user is not prompted again." 60 ), 61 ) 62 63 device_classes = ArrayField( 64 models.TextField(choices=DeviceClasses.choices), 65 help_text=_("Device classes which can be used to authenticate"), 66 default=default_device_classes, 67 ) 68 69 last_auth_threshold = models.TextField( 70 default="seconds=0", 71 validators=[timedelta_string_validator], 72 help_text=_( 73 "If any of the user's device has been used within this threshold, this " 74 "stage will be skipped" 75 ), 76 ) 77 78 webauthn_user_verification = models.TextField( 79 help_text=_("Enforce user verification for WebAuthn devices."), 80 choices=UserVerification.choices, 81 default=UserVerification.PREFERRED, 82 ) 83 webauthn_hints = ArrayField( 84 models.TextField(choices=WebAuthnHint.choices), 85 default=list, 86 blank=True, 87 ) 88 webauthn_allowed_device_types = models.ManyToManyField( 89 "authentik_stages_authenticator_webauthn.WebAuthnDeviceType", blank=True 90 ) 91 92 email_otp_throttling_factor = models.FloatField(default=1) 93 sms_otp_throttling_factor = models.FloatField(default=1) 94 totp_otp_throttling_factor = models.FloatField(default=1) 95 static_otp_throttling_factor = models.FloatField(default=1) 96 97 @property 98 def serializer(self) -> type[BaseSerializer]: 99 from authentik.stages.authenticator_validate.api import AuthenticatorValidateStageSerializer 100 101 return AuthenticatorValidateStageSerializer 102 103 @property 104 def view(self) -> type[View]: 105 from authentik.stages.authenticator_validate.stage import AuthenticatorValidateStageView 106 107 return AuthenticatorValidateStageView 108 109 @property 110 def component(self) -> str: 111 return "ak-stage-authenticator-validate-form" 112 113 def get_throttling_factor(self, device_class: DeviceClasses) -> float | None: 114 if device_class == DeviceClasses.EMAIL: 115 return self.email_otp_throttling_factor 116 elif device_class == DeviceClasses.SMS: 117 return self.sms_otp_throttling_factor 118 elif device_class == DeviceClasses.TOTP: 119 return self.totp_otp_throttling_factor 120 elif device_class == DeviceClasses.STATIC: 121 return self.static_otp_throttling_factor 122 return None 123 124 class Meta: 125 verbose_name = _("Authenticator Validation Stage") 126 verbose_name_plural = _("Authenticator Validation Stages")
Validate user's configured Multi Factor Authentication.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
Accessor to the related objects manager on the forward and reverse sides of a many-to-many relation.
In the example::
class Pizza(Model):
toppings = ManyToManyField(Topping, related_name='pizzas')
Pizza.toppings and Topping.pizzas are ManyToManyDescriptor
instances.
Most of the implementation is delegated to a dynamically defined manager
class built by create_forward_many_to_many_manager() defined below.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
Accessor to the related objects manager on the forward and reverse sides of a many-to-many relation.
In the example::
class Pizza(Model):
toppings = ManyToManyField(Topping, related_name='pizzas')
Pizza.toppings and Topping.pizzas are ManyToManyDescriptor
instances.
Most of the implementation is delegated to a dynamically defined manager
class built by create_forward_many_to_many_manager() defined below.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
97 @property 98 def serializer(self) -> type[BaseSerializer]: 99 from authentik.stages.authenticator_validate.api import AuthenticatorValidateStageSerializer 100 101 return AuthenticatorValidateStageSerializer
Get serializer for this model
103 @property 104 def view(self) -> type[View]: 105 from authentik.stages.authenticator_validate.stage import AuthenticatorValidateStageView 106 107 return AuthenticatorValidateStageView
Return StageView class that implements logic for this stage
113 def get_throttling_factor(self, device_class: DeviceClasses) -> float | None: 114 if device_class == DeviceClasses.EMAIL: 115 return self.email_otp_throttling_factor 116 elif device_class == DeviceClasses.SMS: 117 return self.sms_otp_throttling_factor 118 elif device_class == DeviceClasses.TOTP: 119 return self.totp_otp_throttling_factor 120 elif device_class == DeviceClasses.STATIC: 121 return self.static_otp_throttling_factor 122 return None
Method descriptor with partial application of the given arguments and keywords.
Supports wrapping existing descriptors and handles non-descriptor callables as instance methods.
Method descriptor with partial application of the given arguments and keywords.
Supports wrapping existing descriptors and handles non-descriptor callables as instance methods.
Accessor to the related object on the forward side of a one-to-one relation.
In the example::
class Restaurant(Model):
place = OneToOneField(Place, related_name='restaurant')
Restaurant.place is a ForwardOneToOneDescriptor instance.
Accessor to the related objects manager on the reverse side of a many-to-one relation.
In the example::
class Child(Model):
parent = ForeignKey(Parent, related_name='children')
Parent.children is a ReverseManyToOneDescriptor instance.
Most of the implementation is delegated to a dynamically defined manager
class built by create_forward_many_to_many_manager() defined below.
Inherited Members
- authentik.flows.models.Stage
- stage_uuid
- name
- objects
- ui_user_settings
- is_in_memory
- flow_set
- flowstagebinding_set
- emailstage
- endpointstage
- invitationstage
- passwordstage
- promptstage
- authenticatorstaticstage
- authenticatorduostage
- authenticatoremailstage
- authenticatorsmsstage
- authenticatorwebauthnstage
- authenticatorvalidatestage
- captchastage
- identificationstage
- authenticatortotpstage
- consentstage
- denystage
- dummystage
- redirectstage
- userdeletestage
- userloginstage
- userlogoutstage
- userwritestage
- accountlockdownstage
- authenticatorendpointgdtcstage
- mutualtlsstage
- sourcestage
The requested object does not exist
The query returned multiple objects when only one was expected.