authentik.stages.authenticator_webauthn.models

WebAuthn stage

  1"""WebAuthn stage"""
  2
  3from cryptography.x509 import Certificate, load_pem_x509_certificate
  4from django.contrib.auth import get_user_model
  5from django.contrib.postgres.fields.array import ArrayField
  6from django.db import models
  7from django.utils.timezone import now
  8from django.utils.translation import gettext_lazy as _
  9from django.views import View
 10from rest_framework.serializers import BaseSerializer, Serializer
 11from webauthn.helpers.base64url_to_bytes import base64url_to_bytes
 12from webauthn.helpers.structs import PublicKeyCredentialDescriptor
 13
 14from authentik.core.types import UserSettingSerializer
 15from authentik.flows.models import ConfigurableStage, FriendlyNamedStage, Stage
 16from authentik.lib.models import InternallyManagedMixin, SerializerModel
 17from authentik.stages.authenticator.models import Device
 18
 19UNKNOWN_DEVICE_TYPE_AAGUID = "00000000-0000-0000-0000-000000000000"
 20
 21
 22class UserVerification(models.TextChoices):
 23    """The degree to which the Relying Party wishes to verify a user's identity.
 24
 25    Members:
 26        `REQUIRED`: User verification must occur
 27        `PREFERRED`: User verification would be great, but if not that's okay too
 28        `DISCOURAGED`: User verification should not occur, but it's okay if it does
 29
 30    https://www.w3.org/TR/webauthn-2/#enumdef-userverificationrequirement
 31    """
 32
 33    REQUIRED = "required"
 34    PREFERRED = "preferred"
 35    DISCOURAGED = "discouraged"
 36
 37
 38class ResidentKeyRequirement(models.TextChoices):
 39    """The Relying Party's preference for the authenticator to create a dedicated "client-side"
 40    credential for it. Requiring an authenticator to store a dedicated credential should not be
 41    done lightly due to the limited storage capacity of some types of authenticators.
 42
 43    Members:
 44        `DISCOURAGED`: The authenticator should not create a dedicated credential
 45        `PREFERRED`: The authenticator can create and store a dedicated credential, but if it
 46            doesn't that's alright too
 47        `REQUIRED`: The authenticator MUST create a dedicated credential. If it cannot, the RP
 48            is prepared for an error to occur.
 49
 50    https://www.w3.org/TR/webauthn-2/#enum-residentKeyRequirement
 51    """
 52
 53    DISCOURAGED = "discouraged"
 54    PREFERRED = "preferred"
 55    REQUIRED = "required"
 56
 57
 58class AuthenticatorAttachment(models.TextChoices):
 59    """How an authenticator is connected to the client/browser.
 60
 61    Members:
 62        `PLATFORM`: A non-removable authenticator, like TouchID or Windows Hello
 63        `CROSS_PLATFORM`: A "roaming" authenticator, like a YubiKey
 64
 65    https://www.w3.org/TR/webauthn-2/#enumdef-authenticatorattachment
 66    """
 67
 68    PLATFORM = "platform"
 69    CROSS_PLATFORM = "cross-platform"
 70
 71
 72class WebAuthnHint(models.TextChoices):
 73    """Hints to guide the browser in prioritizing the preferred authenticator during
 74    WebAuthn registration and authentication. Unlike authenticatorAttachment, hints are
 75    advisory and browsers may ignore them.
 76
 77    Members:
 78        `SECURITY_KEY`: A portable FIDO2 authenticator, like a YubiKey
 79        `CLIENT_DEVICE`: The device WebAuthn is being called on, like TouchID or Windows Hello
 80        `HYBRID`: A platform authenticator on a mobile device, accessed via QR code
 81
 82    https://w3c.github.io/webauthn/#enumdef-publickeycredentialhint
 83    """
 84
 85    SECURITY_KEY = "security-key"
 86    CLIENT_DEVICE = "client-device"
 87    HYBRID = "hybrid"
 88
 89
 90class AuthenticatorWebAuthnStage(ConfigurableStage, FriendlyNamedStage, Stage):
 91    """Setup WebAuthn-based authentication for the user."""
 92
 93    user_verification = models.TextField(
 94        choices=UserVerification.choices,
 95        default=UserVerification.PREFERRED,
 96    )
 97    resident_key_requirement = models.TextField(
 98        choices=ResidentKeyRequirement.choices,
 99        default=ResidentKeyRequirement.PREFERRED,
100    )
101    authenticator_attachment = models.TextField(  # noqa: DJ001
102        choices=AuthenticatorAttachment.choices, default=None, null=True
103    )
104
105    prevent_duplicate_devices = models.BooleanField(
106        default=True, help_text=_("When enabled, a given device can only be registered once.")
107    )
108    hints = ArrayField(
109        models.TextField(choices=WebAuthnHint.choices),
110        default=list,
111        blank=True,
112    )
113
114    device_type_restrictions = models.ManyToManyField("WebAuthnDeviceType", blank=True)
115
116    max_attempts = models.PositiveIntegerField(default=0)
117
118    @property
119    def serializer(self) -> type[BaseSerializer]:
120        from authentik.stages.authenticator_webauthn.api.stages import (
121            AuthenticatorWebAuthnStageSerializer,
122        )
123
124        return AuthenticatorWebAuthnStageSerializer
125
126    @property
127    def view(self) -> type[View]:
128        from authentik.stages.authenticator_webauthn.stage import AuthenticatorWebAuthnStageView
129
130        return AuthenticatorWebAuthnStageView
131
132    @property
133    def component(self) -> str:
134        return "ak-stage-authenticator-webauthn-form"
135
136    def ui_user_settings(self) -> UserSettingSerializer | None:
137        return UserSettingSerializer(
138            data={
139                "title": self.friendly_name or str(self._meta.verbose_name),
140                "component": "ak-user-settings-authenticator-webauthn",
141            }
142        )
143
144    def __str__(self) -> str:
145        return f"WebAuthn Authenticator Setup Stage {self.name}"
146
147    class Meta:
148        verbose_name = _("WebAuthn Authenticator Setup Stage")
149        verbose_name_plural = _("WebAuthn Authenticator Setup Stages")
150
151
152class WebAuthnDevice(SerializerModel, Device):
153    """WebAuthn Device for a single user"""
154
155    user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
156
157    name = models.TextField(max_length=200)
158    credential_id = models.TextField(unique=True)
159    public_key = models.TextField()
160    sign_count = models.IntegerField(default=0)
161    rp_id = models.CharField(max_length=253)
162
163    created_on = models.DateTimeField(auto_now_add=True)
164    last_t = models.DateTimeField(default=now)
165
166    attestation_certificate_pem = models.TextField(null=True, default=None)
167    attestation_certificate_fingerprint = models.TextField(null=True, default=None)
168    aaguid = models.TextField(default=UNKNOWN_DEVICE_TYPE_AAGUID)
169    device_type = models.ForeignKey(
170        "WebAuthnDeviceType", on_delete=models.SET_DEFAULT, null=True, default=None
171    )
172
173    @property
174    def descriptor(self) -> PublicKeyCredentialDescriptor:
175        """Get a publickeydescriptor for this device"""
176        return PublicKeyCredentialDescriptor(id=base64url_to_bytes(self.credential_id))
177
178    @property
179    def attestation_certificate(self) -> Certificate | None:
180        if not self.attestation_certificate_pem:
181            return None
182        return load_pem_x509_certificate(self.attestation_certificate_pem.encode())
183
184    def set_sign_count(self, sign_count: int) -> None:
185        """Set the sign_count and update the last_t datetime."""
186        self.sign_count = sign_count
187        self.last_t = now()
188        self.save()
189
190    @property
191    def serializer(self) -> Serializer:
192        from authentik.stages.authenticator_webauthn.api.devices import WebAuthnDeviceSerializer
193
194        return WebAuthnDeviceSerializer
195
196    def __str__(self):
197        return str(self.name) or str(self.user_id)
198
199    class Meta:
200        verbose_name = _("WebAuthn Device")
201        verbose_name_plural = _("WebAuthn Devices")
202
203
204class WebAuthnDeviceType(InternallyManagedMixin, SerializerModel):
205    """WebAuthn device type, used to restrict which device types are allowed"""
206
207    aaguid = models.UUIDField(primary_key=True, unique=True)
208
209    description = models.TextField()
210    icon = models.TextField(null=True)
211
212    @property
213    def serializer(self) -> Serializer:
214        from authentik.stages.authenticator_webauthn.api.device_types import (
215            WebAuthnDeviceTypeSerializer,
216        )
217
218        return WebAuthnDeviceTypeSerializer
219
220    class Meta:
221        verbose_name = _("WebAuthn Device type")
222        verbose_name_plural = _("WebAuthn Device types")
223
224    def __str__(self) -> str:
225        return f"WebAuthn device type {self.description} ({self.aaguid})"
UNKNOWN_DEVICE_TYPE_AAGUID = '00000000-0000-0000-0000-000000000000'
class UserVerification(django.db.models.enums.TextChoices):
23class UserVerification(models.TextChoices):
24    """The degree to which the Relying Party wishes to verify a user's identity.
25
26    Members:
27        `REQUIRED`: User verification must occur
28        `PREFERRED`: User verification would be great, but if not that's okay too
29        `DISCOURAGED`: User verification should not occur, but it's okay if it does
30
31    https://www.w3.org/TR/webauthn-2/#enumdef-userverificationrequirement
32    """
33
34    REQUIRED = "required"
35    PREFERRED = "preferred"
36    DISCOURAGED = "discouraged"

The degree to which the Relying Party wishes to verify a user's identity.

Members: REQUIRED: User verification must occur PREFERRED: User verification would be great, but if not that's okay too DISCOURAGED: User verification should not occur, but it's okay if it does

https://www.w3.org/TR/webauthn-2/#enumdef-userverificationrequirement

class ResidentKeyRequirement(django.db.models.enums.TextChoices):
39class ResidentKeyRequirement(models.TextChoices):
40    """The Relying Party's preference for the authenticator to create a dedicated "client-side"
41    credential for it. Requiring an authenticator to store a dedicated credential should not be
42    done lightly due to the limited storage capacity of some types of authenticators.
43
44    Members:
45        `DISCOURAGED`: The authenticator should not create a dedicated credential
46        `PREFERRED`: The authenticator can create and store a dedicated credential, but if it
47            doesn't that's alright too
48        `REQUIRED`: The authenticator MUST create a dedicated credential. If it cannot, the RP
49            is prepared for an error to occur.
50
51    https://www.w3.org/TR/webauthn-2/#enum-residentKeyRequirement
52    """
53
54    DISCOURAGED = "discouraged"
55    PREFERRED = "preferred"
56    REQUIRED = "required"

The Relying Party's preference for the authenticator to create a dedicated "client-side" credential for it. Requiring an authenticator to store a dedicated credential should not be done lightly due to the limited storage capacity of some types of authenticators.

Members: DISCOURAGED: The authenticator should not create a dedicated credential PREFERRED: The authenticator can create and store a dedicated credential, but if it doesn't that's alright too REQUIRED: The authenticator MUST create a dedicated credential. If it cannot, the RP is prepared for an error to occur.

https://www.w3.org/TR/webauthn-2/#enum-residentKeyRequirement

class AuthenticatorAttachment(django.db.models.enums.TextChoices):
59class AuthenticatorAttachment(models.TextChoices):
60    """How an authenticator is connected to the client/browser.
61
62    Members:
63        `PLATFORM`: A non-removable authenticator, like TouchID or Windows Hello
64        `CROSS_PLATFORM`: A "roaming" authenticator, like a YubiKey
65
66    https://www.w3.org/TR/webauthn-2/#enumdef-authenticatorattachment
67    """
68
69    PLATFORM = "platform"
70    CROSS_PLATFORM = "cross-platform"

How an authenticator is connected to the client/browser.

Members: PLATFORM: A non-removable authenticator, like TouchID or Windows Hello CROSS_PLATFORM: A "roaming" authenticator, like a YubiKey

https://www.w3.org/TR/webauthn-2/#enumdef-authenticatorattachment

class WebAuthnHint(django.db.models.enums.TextChoices):
73class WebAuthnHint(models.TextChoices):
74    """Hints to guide the browser in prioritizing the preferred authenticator during
75    WebAuthn registration and authentication. Unlike authenticatorAttachment, hints are
76    advisory and browsers may ignore them.
77
78    Members:
79        `SECURITY_KEY`: A portable FIDO2 authenticator, like a YubiKey
80        `CLIENT_DEVICE`: The device WebAuthn is being called on, like TouchID or Windows Hello
81        `HYBRID`: A platform authenticator on a mobile device, accessed via QR code
82
83    https://w3c.github.io/webauthn/#enumdef-publickeycredentialhint
84    """
85
86    SECURITY_KEY = "security-key"
87    CLIENT_DEVICE = "client-device"
88    HYBRID = "hybrid"

Hints to guide the browser in prioritizing the preferred authenticator during WebAuthn registration and authentication. Unlike authenticatorAttachment, hints are advisory and browsers may ignore them.

Members: SECURITY_KEY: A portable FIDO2 authenticator, like a YubiKey CLIENT_DEVICE: The device WebAuthn is being called on, like TouchID or Windows Hello HYBRID: A platform authenticator on a mobile device, accessed via QR code

https://w3c.github.io/webauthn/#enumdef-publickeycredentialhint

SECURITY_KEY = WebAuthnHint.SECURITY_KEY
CLIENT_DEVICE = WebAuthnHint.CLIENT_DEVICE
 91class AuthenticatorWebAuthnStage(ConfigurableStage, FriendlyNamedStage, Stage):
 92    """Setup WebAuthn-based authentication for the user."""
 93
 94    user_verification = models.TextField(
 95        choices=UserVerification.choices,
 96        default=UserVerification.PREFERRED,
 97    )
 98    resident_key_requirement = models.TextField(
 99        choices=ResidentKeyRequirement.choices,
100        default=ResidentKeyRequirement.PREFERRED,
101    )
102    authenticator_attachment = models.TextField(  # noqa: DJ001
103        choices=AuthenticatorAttachment.choices, default=None, null=True
104    )
105
106    prevent_duplicate_devices = models.BooleanField(
107        default=True, help_text=_("When enabled, a given device can only be registered once.")
108    )
109    hints = ArrayField(
110        models.TextField(choices=WebAuthnHint.choices),
111        default=list,
112        blank=True,
113    )
114
115    device_type_restrictions = models.ManyToManyField("WebAuthnDeviceType", blank=True)
116
117    max_attempts = models.PositiveIntegerField(default=0)
118
119    @property
120    def serializer(self) -> type[BaseSerializer]:
121        from authentik.stages.authenticator_webauthn.api.stages import (
122            AuthenticatorWebAuthnStageSerializer,
123        )
124
125        return AuthenticatorWebAuthnStageSerializer
126
127    @property
128    def view(self) -> type[View]:
129        from authentik.stages.authenticator_webauthn.stage import AuthenticatorWebAuthnStageView
130
131        return AuthenticatorWebAuthnStageView
132
133    @property
134    def component(self) -> str:
135        return "ak-stage-authenticator-webauthn-form"
136
137    def ui_user_settings(self) -> UserSettingSerializer | None:
138        return UserSettingSerializer(
139            data={
140                "title": self.friendly_name or str(self._meta.verbose_name),
141                "component": "ak-user-settings-authenticator-webauthn",
142            }
143        )
144
145    def __str__(self) -> str:
146        return f"WebAuthn Authenticator Setup Stage {self.name}"
147
148    class Meta:
149        verbose_name = _("WebAuthn Authenticator Setup Stage")
150        verbose_name_plural = _("WebAuthn Authenticator Setup Stages")

Setup WebAuthn-based authentication for the user.

def user_verification(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def resident_key_requirement(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def authenticator_attachment(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def prevent_duplicate_devices(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def hints(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

device_type_restrictions

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.

def max_attempts(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

serializer: type[rest_framework.serializers.BaseSerializer]
119    @property
120    def serializer(self) -> type[BaseSerializer]:
121        from authentik.stages.authenticator_webauthn.api.stages import (
122            AuthenticatorWebAuthnStageSerializer,
123        )
124
125        return AuthenticatorWebAuthnStageSerializer

Get serializer for this model

view: type[django.views.generic.base.View]
127    @property
128    def view(self) -> type[View]:
129        from authentik.stages.authenticator_webauthn.stage import AuthenticatorWebAuthnStageView
130
131        return AuthenticatorWebAuthnStageView

Return StageView class that implements logic for this stage

component: str
133    @property
134    def component(self) -> str:
135        return "ak-stage-authenticator-webauthn-form"

Return component used to edit this object

def ui_user_settings(self) -> authentik.core.types.UserSettingSerializer | None:
137    def ui_user_settings(self) -> UserSettingSerializer | None:
138        return UserSettingSerializer(
139            data={
140                "title": self.friendly_name or str(self._meta.verbose_name),
141                "component": "ak-user-settings-authenticator-webauthn",
142            }
143        )

Entrypoint to integrate with User settings. Can either return None if no user settings are available, or a challenge.

configure_flow

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example::

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

def friendly_name(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def get_user_verification_display(unknown):

Method descriptor with partial application of the given arguments and keywords.

Supports wrapping existing descriptors and handles non-descriptor callables as instance methods.

def get_resident_key_requirement_display(unknown):

Method descriptor with partial application of the given arguments and keywords.

Supports wrapping existing descriptors and handles non-descriptor callables as instance methods.

def get_authenticator_attachment_display(unknown):

Method descriptor with partial application of the given arguments and keywords.

Supports wrapping existing descriptors and handles non-descriptor callables as instance methods.

configure_flow_id
stage_ptr_id
stage_ptr

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.

class AuthenticatorWebAuthnStage.DoesNotExist(authentik.flows.models.Stage.DoesNotExist):

The requested object does not exist

class AuthenticatorWebAuthnStage.MultipleObjectsReturned(authentik.flows.models.Stage.MultipleObjectsReturned):

The query returned multiple objects when only one was expected.

153class WebAuthnDevice(SerializerModel, Device):
154    """WebAuthn Device for a single user"""
155
156    user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
157
158    name = models.TextField(max_length=200)
159    credential_id = models.TextField(unique=True)
160    public_key = models.TextField()
161    sign_count = models.IntegerField(default=0)
162    rp_id = models.CharField(max_length=253)
163
164    created_on = models.DateTimeField(auto_now_add=True)
165    last_t = models.DateTimeField(default=now)
166
167    attestation_certificate_pem = models.TextField(null=True, default=None)
168    attestation_certificate_fingerprint = models.TextField(null=True, default=None)
169    aaguid = models.TextField(default=UNKNOWN_DEVICE_TYPE_AAGUID)
170    device_type = models.ForeignKey(
171        "WebAuthnDeviceType", on_delete=models.SET_DEFAULT, null=True, default=None
172    )
173
174    @property
175    def descriptor(self) -> PublicKeyCredentialDescriptor:
176        """Get a publickeydescriptor for this device"""
177        return PublicKeyCredentialDescriptor(id=base64url_to_bytes(self.credential_id))
178
179    @property
180    def attestation_certificate(self) -> Certificate | None:
181        if not self.attestation_certificate_pem:
182            return None
183        return load_pem_x509_certificate(self.attestation_certificate_pem.encode())
184
185    def set_sign_count(self, sign_count: int) -> None:
186        """Set the sign_count and update the last_t datetime."""
187        self.sign_count = sign_count
188        self.last_t = now()
189        self.save()
190
191    @property
192    def serializer(self) -> Serializer:
193        from authentik.stages.authenticator_webauthn.api.devices import WebAuthnDeviceSerializer
194
195        return WebAuthnDeviceSerializer
196
197    def __str__(self):
198        return str(self.name) or str(self.user_id)
199
200    class Meta:
201        verbose_name = _("WebAuthn Device")
202        verbose_name_plural = _("WebAuthn Devices")

WebAuthn Device for a single user

user

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example::

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

def name(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def credential_id(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def public_key(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def sign_count(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def rp_id(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def created_on(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def last_t(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def attestation_certificate_pem(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def attestation_certificate_fingerprint(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def aaguid(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

device_type

Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.

In the example::

class Child(Model):
    parent = ForeignKey(Parent, related_name='children')

Child.parent is a ForwardManyToOneDescriptor instance.

descriptor: webauthn.helpers.structs.PublicKeyCredentialDescriptor
174    @property
175    def descriptor(self) -> PublicKeyCredentialDescriptor:
176        """Get a publickeydescriptor for this device"""
177        return PublicKeyCredentialDescriptor(id=base64url_to_bytes(self.credential_id))

Get a publickeydescriptor for this device

attestation_certificate: cryptography.hazmat.bindings._rust.x509.Certificate | None
179    @property
180    def attestation_certificate(self) -> Certificate | None:
181        if not self.attestation_certificate_pem:
182            return None
183        return load_pem_x509_certificate(self.attestation_certificate_pem.encode())
def set_sign_count(self, sign_count: int) -> None:
185    def set_sign_count(self, sign_count: int) -> None:
186        """Set the sign_count and update the last_t datetime."""
187        self.sign_count = sign_count
188        self.last_t = now()
189        self.save()

Set the sign_count and update the last_t datetime.

serializer: rest_framework.serializers.Serializer
191    @property
192    def serializer(self) -> Serializer:
193        from authentik.stages.authenticator_webauthn.api.devices import WebAuthnDeviceSerializer
194
195        return WebAuthnDeviceSerializer

Get serializer for this model

def confirmed(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def last_used(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def created(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def last_updated(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

user_id
def get_next_by_created_on(unknown):

Method descriptor with partial application of the given arguments and keywords.

Supports wrapping existing descriptors and handles non-descriptor callables as instance methods.

def get_previous_by_created_on(unknown):

Method descriptor with partial application of the given arguments and keywords.

Supports wrapping existing descriptors and handles non-descriptor callables as instance methods.

def get_next_by_last_t(unknown):

Method descriptor with partial application of the given arguments and keywords.

Supports wrapping existing descriptors and handles non-descriptor callables as instance methods.

def get_previous_by_last_t(unknown):

Method descriptor with partial application of the given arguments and keywords.

Supports wrapping existing descriptors and handles non-descriptor callables as instance methods.

device_type_id
def get_next_by_created(unknown):

Method descriptor with partial application of the given arguments and keywords.

Supports wrapping existing descriptors and handles non-descriptor callables as instance methods.

def get_previous_by_created(unknown):

Method descriptor with partial application of the given arguments and keywords.

Supports wrapping existing descriptors and handles non-descriptor callables as instance methods.

def get_next_by_last_updated(unknown):

Method descriptor with partial application of the given arguments and keywords.

Supports wrapping existing descriptors and handles non-descriptor callables as instance methods.

def get_previous_by_last_updated(unknown):

Method descriptor with partial application of the given arguments and keywords.

Supports wrapping existing descriptors and handles non-descriptor callables as instance methods.

def id(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

class WebAuthnDevice.DoesNotExist(django.core.exceptions.ObjectDoesNotExist):

The requested object does not exist

class WebAuthnDevice.MultipleObjectsReturned(django.core.exceptions.MultipleObjectsReturned):

The query returned multiple objects when only one was expected.

205class WebAuthnDeviceType(InternallyManagedMixin, SerializerModel):
206    """WebAuthn device type, used to restrict which device types are allowed"""
207
208    aaguid = models.UUIDField(primary_key=True, unique=True)
209
210    description = models.TextField()
211    icon = models.TextField(null=True)
212
213    @property
214    def serializer(self) -> Serializer:
215        from authentik.stages.authenticator_webauthn.api.device_types import (
216            WebAuthnDeviceTypeSerializer,
217        )
218
219        return WebAuthnDeviceTypeSerializer
220
221    class Meta:
222        verbose_name = _("WebAuthn Device type")
223        verbose_name_plural = _("WebAuthn Device types")
224
225    def __str__(self) -> str:
226        return f"WebAuthn device type {self.description} ({self.aaguid})"

WebAuthn device type, used to restrict which device types are allowed

def aaguid(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def description(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

def icon(unknown):

A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.

serializer: rest_framework.serializers.Serializer
213    @property
214    def serializer(self) -> Serializer:
215        from authentik.stages.authenticator_webauthn.api.device_types import (
216            WebAuthnDeviceTypeSerializer,
217        )
218
219        return WebAuthnDeviceTypeSerializer

Get serializer for this model

def objects(unknown):

The type of the None singleton.

authenticatorwebauthnstage_set

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.

webauthndevice_set

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.

authenticatorvalidatestage_set

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.

class WebAuthnDeviceType.DoesNotExist(django.core.exceptions.ObjectDoesNotExist):

The requested object does not exist

class WebAuthnDeviceType.MultipleObjectsReturned(django.core.exceptions.MultipleObjectsReturned):

The query returned multiple objects when only one was expected.