authentik.flows.models

Flow models

  1"""Flow models"""
  2
  3from base64 import b64decode, b64encode
  4from pickle import dumps, loads  # nosec
  5from typing import TYPE_CHECKING
  6from uuid import uuid4
  7
  8from django.core.validators import validate_slug
  9from django.db import models
 10from django.http import HttpRequest
 11from django.utils.translation import gettext_lazy as _
 12from model_utils.managers import InheritanceManager
 13from rest_framework.serializers import BaseSerializer
 14from structlog.stdlib import get_logger
 15
 16from authentik.admin.files.fields import FileField
 17from authentik.admin.files.manager import get_file_manager
 18from authentik.admin.files.usage import FileUsage
 19from authentik.core.models import Token
 20from authentik.core.types import UserSettingSerializer
 21from authentik.flows.challenge import FlowLayout
 22from authentik.lib.config import CONFIG
 23from authentik.lib.models import InheritanceForeignKey, InternallyManagedMixin, SerializerModel
 24from authentik.lib.utils.reflection import class_to_path
 25from authentik.policies.models import PolicyBindingModel
 26
 27if TYPE_CHECKING:
 28    from authentik.flows.planner import FlowPlan
 29    from authentik.flows.stage import StageView
 30
 31LOGGER = get_logger()
 32
 33
 34class FlowAuthenticationRequirement(models.TextChoices):
 35    """Required level of authentication and authorization to access a flow"""
 36
 37    NONE = "none"
 38    REQUIRE_AUTHENTICATED = "require_authenticated"
 39    REQUIRE_UNAUTHENTICATED = "require_unauthenticated"
 40    REQUIRE_SUPERUSER = "require_superuser"
 41    REQUIRE_REDIRECT = "require_redirect"
 42    REQUIRE_OUTPOST = "require_outpost"
 43    REQUIRE_TOKEN = "require_token"
 44
 45
 46class NotConfiguredAction(models.TextChoices):
 47    """Decides how the FlowExecutor should proceed when a stage isn't configured"""
 48
 49    SKIP = "skip"
 50    DENY = "deny"
 51    CONFIGURE = "configure"
 52
 53
 54class InvalidResponseAction(models.TextChoices):
 55    """Configure how the flow executor should handle invalid responses to challenges"""
 56
 57    RETRY = "retry"
 58    RESTART = "restart"
 59    RESTART_WITH_CONTEXT = "restart_with_context"
 60
 61
 62class FlowDeniedAction(models.TextChoices):
 63    """Configure what response is given to denied flow executions"""
 64
 65    MESSAGE_CONTINUE = "message_continue"
 66    MESSAGE = "message"
 67    CONTINUE = "continue"
 68
 69
 70class FlowDesignation(models.TextChoices):
 71    """Designation of what a Flow should be used for. At a later point, this
 72    should be replaced by a database entry."""
 73
 74    AUTHENTICATION = "authentication"
 75    AUTHORIZATION = "authorization"
 76    INVALIDATION = "invalidation"
 77    ENROLLMENT = "enrollment"
 78    UNRENOLLMENT = "unenrollment"
 79    RECOVERY = "recovery"
 80    STAGE_CONFIGURATION = "stage_configuration"
 81
 82
 83class Stage(SerializerModel):
 84    """Stage is an instance of a component used in a flow. This can verify the user,
 85    enroll the user or offer a way of recovery"""
 86
 87    stage_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4)
 88
 89    name = models.TextField(unique=True)
 90
 91    objects = InheritanceManager()
 92
 93    @property
 94    def view(self) -> type[StageView]:
 95        """Return StageView class that implements logic for this stage"""
 96        # This is a bit of a workaround, since we can't set class methods with setattr
 97        if hasattr(self, "__in_memory_type"):
 98            return getattr(self, "__in_memory_type")
 99        raise NotImplementedError
100
101    @property
102    def component(self) -> str:
103        """Return component used to edit this object"""
104        raise NotImplementedError
105
106    def ui_user_settings(self) -> UserSettingSerializer | None:
107        """Entrypoint to integrate with User settings. Can either return None if no
108        user settings are available, or a challenge."""
109        return None
110
111    @property
112    def is_in_memory(self):
113        return hasattr(self, "__in_memory_type")
114
115    def __str__(self):
116        if self.is_in_memory:
117            return f"In-memory Stage {getattr(self, '__in_memory_type')}"
118        return f"Stage {self.name}"
119
120
121def in_memory_stage(view: type[StageView], **kwargs) -> Stage:
122    """Creates an in-memory stage instance, based on a `view` as view.
123    Any key-word arguments are set as attributes on the stage object,
124    accessible via `self.executor.current_stage`."""
125    stage = Stage()
126    # Because we can't pickle a locally generated function,
127    # we set the view as a separate property and reference a generic function
128    # that returns that member
129    setattr(stage, "__in_memory_type", view)
130    stage.name = _("Dynamic In-memory stage: {doc}".format_map({"doc": view.__doc__}))
131    stage._meta.verbose_name = class_to_path(view)
132    for key, value in kwargs.items():
133        setattr(stage, key, value)
134    return stage
135
136
137class Flow(SerializerModel, PolicyBindingModel):
138    """Flow describes how a series of Stages should be executed to authenticate/enroll/recover
139    a user. Additionally, policies can be applied, to specify which users
140    have access to this flow."""
141
142    flow_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4)
143
144    name = models.TextField()
145    slug = models.TextField(
146        validators=[validate_slug],
147        unique=True,
148        help_text=_("Visible in the URL."),
149    )
150
151    title = models.TextField(help_text=_("Shown as the Title in Flow pages."))
152    layout = models.TextField(default=FlowLayout.STACKED, choices=FlowLayout.choices)
153
154    designation = models.CharField(
155        max_length=100,
156        choices=FlowDesignation.choices,
157        help_text=_(
158            "Decides what this Flow is used for. For example, the Authentication flow "
159            "is redirect to when an un-authenticated user visits authentik."
160        ),
161    )
162
163    background = FileField(
164        blank=True,
165        default="",
166        help_text=_("Background shown during execution"),
167    )
168
169    compatibility_mode = models.BooleanField(
170        default=False,
171        help_text=_(
172            "Enable compatibility mode, increases compatibility with "
173            "password managers on mobile devices."
174        ),
175    )
176
177    denied_action = models.TextField(
178        choices=FlowDeniedAction.choices,
179        default=FlowDeniedAction.MESSAGE_CONTINUE,
180        help_text=_("Configure what should happen when a flow denies access to a user."),
181    )
182
183    authentication = models.TextField(
184        choices=FlowAuthenticationRequirement.choices,
185        default=FlowAuthenticationRequirement.NONE,
186        help_text=_("Required level of authentication and authorization to access a flow."),
187    )
188
189    def background_url(
190        self,
191        request: HttpRequest | None = None,
192        use_cache: bool = True,
193    ) -> str:
194        """Get the URL to the background image"""
195        if not self.background:
196            if request:
197                return request.brand.branding_default_flow_background_url(
198                    request,
199                    use_cache=use_cache,
200                )
201            return (
202                CONFIG.get("web.path", "/")[:-1] + "/static/dist/assets/images/flow_background.jpg"
203            )
204
205        return get_file_manager(FileUsage.MEDIA).file_url(
206            self.background,
207            request,
208            use_cache=use_cache,
209        )
210
211    def background_themed_urls(
212        self,
213        request: HttpRequest | None = None,
214        use_cache: bool = True,
215    ) -> dict[str, str] | None:
216        """Get themed URLs for background if it contains %(theme)s"""
217        if not self.background:
218            if request:
219                return request.brand.branding_default_flow_background_themed_urls(
220                    request,
221                    use_cache=use_cache,
222                )
223            return None
224
225        return get_file_manager(FileUsage.MEDIA).themed_urls(
226            self.background,
227            request,
228            use_cache=use_cache,
229        )
230
231    stages = models.ManyToManyField(Stage, through="FlowStageBinding", blank=True)
232
233    @property
234    def serializer(self) -> type[BaseSerializer]:
235        from authentik.flows.api.flows import FlowSerializer
236
237        return FlowSerializer
238
239    def __str__(self) -> str:
240        return f"Flow {self.name} ({self.slug})"
241
242    class Meta:
243        verbose_name = _("Flow")
244        verbose_name_plural = _("Flows")
245
246        permissions = [
247            ("export_flow", _("Can export a Flow")),
248            ("inspect_flow", _("Can inspect a Flow's execution")),
249            ("view_flow_cache", _("View Flow's cache metrics")),
250            ("clear_flow_cache", _("Clear Flow's cache metrics")),
251        ]
252
253
254class FlowStageBinding(SerializerModel, PolicyBindingModel):
255    """Relationship between Flow and Stage. Order is required and unique for
256    each flow-stage Binding. Additionally, policies can be specified, which determine if
257    this Binding applies to the current user"""
258
259    fsb_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4)
260
261    target = models.ForeignKey("Flow", on_delete=models.CASCADE)
262    stage = InheritanceForeignKey(Stage, on_delete=models.CASCADE)
263
264    evaluate_on_plan = models.BooleanField(
265        default=False,
266        help_text=_("Evaluate policies during the Flow planning process."),
267    )
268    re_evaluate_policies = models.BooleanField(
269        default=True,
270        help_text=_("Evaluate policies when the Stage is presented to the user."),
271    )
272
273    invalid_response_action = models.TextField(
274        choices=InvalidResponseAction.choices,
275        default=InvalidResponseAction.RETRY,
276        help_text=_(
277            "Configure how the flow executor should handle an invalid response to a "
278            "challenge. RETRY returns the error message and a similar challenge to the "
279            "executor. RESTART restarts the flow from the beginning, and RESTART_WITH_CONTEXT "
280            "restarts the flow while keeping the current context."
281        ),
282    )
283
284    order = models.IntegerField()
285
286    objects = InheritanceManager()
287
288    @property
289    def serializer(self) -> type[BaseSerializer]:
290        from authentik.flows.api.bindings import FlowStageBindingSerializer
291
292        return FlowStageBindingSerializer
293
294    def __str__(self) -> str:
295        if not self.target_id and self.stage_id:
296            return f"In-memory Flow-stage binding {self.stage}"
297        return f"Flow-stage binding #{self.order} to {self.target_id}"
298
299    class Meta:
300        ordering = ["target", "order"]
301
302        verbose_name = _("Flow Stage Binding")
303        verbose_name_plural = _("Flow Stage Bindings")
304        unique_together = (("target", "stage", "order"),)
305
306
307class ConfigurableStage(models.Model):
308    """Abstract base class for a Stage that can be configured by the enduser.
309    The stage should create a default flow with the configure_stage designation during
310    migration."""
311
312    configure_flow = models.ForeignKey(
313        Flow,
314        on_delete=models.SET_NULL,
315        null=True,
316        blank=True,
317        help_text=_(
318            "Flow used by an authenticated user to configure this Stage. "
319            "If empty, user will not be able to configure this stage."
320        ),
321    )
322
323    class Meta:
324        abstract = True
325
326
327class FriendlyNamedStage(models.Model):
328    """Abstract base class for a Stage that can have a user friendly name configured."""
329
330    friendly_name = models.TextField(blank=True)
331
332    class Meta:
333        abstract = True
334
335
336class FlowToken(InternallyManagedMixin, Token):
337    """Subclass of a standard Token, stores the currently active flow plan upon creation.
338    Can be used to later resume a flow."""
339
340    flow = models.ForeignKey(Flow, on_delete=models.CASCADE)
341    _plan = models.TextField()
342    revoke_on_execution = models.BooleanField(default=True)
343
344    @staticmethod
345    def pickle(plan: FlowPlan) -> str:
346        """Pickle into string"""
347        data = dumps(plan)
348        return b64encode(data).decode()
349
350    @property
351    def plan(self) -> FlowPlan:
352        """Load Flow plan from pickled version"""
353        return loads(b64decode(self._plan.encode()))  # nosec
354
355    def __str__(self) -> str:
356        return f"Flow Token {super().__str__()}"
357
358    class Meta:
359        verbose_name = _("Flow Token")
360        verbose_name_plural = _("Flow Tokens")
LOGGER = <BoundLoggerLazyProxy(logger=None, wrapper_class=None, processors=None, context_class=None, initial_values={}, logger_factory_args=())>
class FlowAuthenticationRequirement(django.db.models.enums.TextChoices):
35class FlowAuthenticationRequirement(models.TextChoices):
36    """Required level of authentication and authorization to access a flow"""
37
38    NONE = "none"
39    REQUIRE_AUTHENTICATED = "require_authenticated"
40    REQUIRE_UNAUTHENTICATED = "require_unauthenticated"
41    REQUIRE_SUPERUSER = "require_superuser"
42    REQUIRE_REDIRECT = "require_redirect"
43    REQUIRE_OUTPOST = "require_outpost"
44    REQUIRE_TOKEN = "require_token"

Required level of authentication and authorization to access a flow

class NotConfiguredAction(django.db.models.enums.TextChoices):
47class NotConfiguredAction(models.TextChoices):
48    """Decides how the FlowExecutor should proceed when a stage isn't configured"""
49
50    SKIP = "skip"
51    DENY = "deny"
52    CONFIGURE = "configure"

Decides how the FlowExecutor should proceed when a stage isn't configured

class InvalidResponseAction(django.db.models.enums.TextChoices):
55class InvalidResponseAction(models.TextChoices):
56    """Configure how the flow executor should handle invalid responses to challenges"""
57
58    RETRY = "retry"
59    RESTART = "restart"
60    RESTART_WITH_CONTEXT = "restart_with_context"

Configure how the flow executor should handle invalid responses to challenges

class FlowDeniedAction(django.db.models.enums.TextChoices):
63class FlowDeniedAction(models.TextChoices):
64    """Configure what response is given to denied flow executions"""
65
66    MESSAGE_CONTINUE = "message_continue"
67    MESSAGE = "message"
68    CONTINUE = "continue"

Configure what response is given to denied flow executions

class FlowDesignation(django.db.models.enums.TextChoices):
71class FlowDesignation(models.TextChoices):
72    """Designation of what a Flow should be used for. At a later point, this
73    should be replaced by a database entry."""
74
75    AUTHENTICATION = "authentication"
76    AUTHORIZATION = "authorization"
77    INVALIDATION = "invalidation"
78    ENROLLMENT = "enrollment"
79    UNRENOLLMENT = "unenrollment"
80    RECOVERY = "recovery"
81    STAGE_CONFIGURATION = "stage_configuration"

Designation of what a Flow should be used for. At a later point, this should be replaced by a database entry.

STAGE_CONFIGURATION = FlowDesignation.STAGE_CONFIGURATION
class Stage(authentik.lib.models.SerializerModel):
 84class Stage(SerializerModel):
 85    """Stage is an instance of a component used in a flow. This can verify the user,
 86    enroll the user or offer a way of recovery"""
 87
 88    stage_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4)
 89
 90    name = models.TextField(unique=True)
 91
 92    objects = InheritanceManager()
 93
 94    @property
 95    def view(self) -> type[StageView]:
 96        """Return StageView class that implements logic for this stage"""
 97        # This is a bit of a workaround, since we can't set class methods with setattr
 98        if hasattr(self, "__in_memory_type"):
 99            return getattr(self, "__in_memory_type")
100        raise NotImplementedError
101
102    @property
103    def component(self) -> str:
104        """Return component used to edit this object"""
105        raise NotImplementedError
106
107    def ui_user_settings(self) -> UserSettingSerializer | None:
108        """Entrypoint to integrate with User settings. Can either return None if no
109        user settings are available, or a challenge."""
110        return None
111
112    @property
113    def is_in_memory(self):
114        return hasattr(self, "__in_memory_type")
115
116    def __str__(self):
117        if self.is_in_memory:
118            return f"In-memory Stage {getattr(self, '__in_memory_type')}"
119        return f"Stage {self.name}"

Stage is an instance of a component used in a flow. This can verify the user, enroll the user or offer a way of recovery

def stage_uuid(unknown):

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

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 objects(unknown):

The type of the None singleton.

view
 94    @property
 95    def view(self) -> type[StageView]:
 96        """Return StageView class that implements logic for this stage"""
 97        # This is a bit of a workaround, since we can't set class methods with setattr
 98        if hasattr(self, "__in_memory_type"):
 99            return getattr(self, "__in_memory_type")
100        raise NotImplementedError

Return StageView class that implements logic for this stage

component: str
102    @property
103    def component(self) -> str:
104        """Return component used to edit this object"""
105        raise NotImplementedError

Return component used to edit this object

def ui_user_settings(self) -> authentik.core.types.UserSettingSerializer | None:
107    def ui_user_settings(self) -> UserSettingSerializer | None:
108        """Entrypoint to integrate with User settings. Can either return None if no
109        user settings are available, or a challenge."""
110        return None

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

is_in_memory
112    @property
113    def is_in_memory(self):
114        return hasattr(self, "__in_memory_type")
flow_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.

flowstagebinding_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.

emailstage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

endpointstage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

invitationstage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

passwordstage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

promptstage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

authenticatorstaticstage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

authenticatorduostage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

authenticatoremailstage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

authenticatorsmsstage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

authenticatorwebauthnstage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

authenticatorvalidatestage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

captchastage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

identificationstage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

authenticatortotpstage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

consentstage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

denystage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

dummystage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

redirectstage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

userdeletestage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

userloginstage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

userlogoutstage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

userwritestage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

accountlockdownstage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

authenticatorendpointgdtcstage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

mutualtlsstage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

sourcestage

Accessor to the related object on the reverse side of a one-to-one relation.

In the example::

class Restaurant(Model):
    place = OneToOneField(Place, related_name='restaurant')

Place.restaurant is a ReverseOneToOneDescriptor instance.

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

The requested object does not exist

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

The query returned multiple objects when only one was expected.

def in_memory_stage(unknown):
122def in_memory_stage(view: type[StageView], **kwargs) -> Stage:
123    """Creates an in-memory stage instance, based on a `view` as view.
124    Any key-word arguments are set as attributes on the stage object,
125    accessible via `self.executor.current_stage`."""
126    stage = Stage()
127    # Because we can't pickle a locally generated function,
128    # we set the view as a separate property and reference a generic function
129    # that returns that member
130    setattr(stage, "__in_memory_type", view)
131    stage.name = _("Dynamic In-memory stage: {doc}".format_map({"doc": view.__doc__}))
132    stage._meta.verbose_name = class_to_path(view)
133    for key, value in kwargs.items():
134        setattr(stage, key, value)
135    return stage

Creates an in-memory stage instance, based on a view as view. Any key-word arguments are set as attributes on the stage object, accessible via self.executor.current_stage.

138class Flow(SerializerModel, PolicyBindingModel):
139    """Flow describes how a series of Stages should be executed to authenticate/enroll/recover
140    a user. Additionally, policies can be applied, to specify which users
141    have access to this flow."""
142
143    flow_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4)
144
145    name = models.TextField()
146    slug = models.TextField(
147        validators=[validate_slug],
148        unique=True,
149        help_text=_("Visible in the URL."),
150    )
151
152    title = models.TextField(help_text=_("Shown as the Title in Flow pages."))
153    layout = models.TextField(default=FlowLayout.STACKED, choices=FlowLayout.choices)
154
155    designation = models.CharField(
156        max_length=100,
157        choices=FlowDesignation.choices,
158        help_text=_(
159            "Decides what this Flow is used for. For example, the Authentication flow "
160            "is redirect to when an un-authenticated user visits authentik."
161        ),
162    )
163
164    background = FileField(
165        blank=True,
166        default="",
167        help_text=_("Background shown during execution"),
168    )
169
170    compatibility_mode = models.BooleanField(
171        default=False,
172        help_text=_(
173            "Enable compatibility mode, increases compatibility with "
174            "password managers on mobile devices."
175        ),
176    )
177
178    denied_action = models.TextField(
179        choices=FlowDeniedAction.choices,
180        default=FlowDeniedAction.MESSAGE_CONTINUE,
181        help_text=_("Configure what should happen when a flow denies access to a user."),
182    )
183
184    authentication = models.TextField(
185        choices=FlowAuthenticationRequirement.choices,
186        default=FlowAuthenticationRequirement.NONE,
187        help_text=_("Required level of authentication and authorization to access a flow."),
188    )
189
190    def background_url(
191        self,
192        request: HttpRequest | None = None,
193        use_cache: bool = True,
194    ) -> str:
195        """Get the URL to the background image"""
196        if not self.background:
197            if request:
198                return request.brand.branding_default_flow_background_url(
199                    request,
200                    use_cache=use_cache,
201                )
202            return (
203                CONFIG.get("web.path", "/")[:-1] + "/static/dist/assets/images/flow_background.jpg"
204            )
205
206        return get_file_manager(FileUsage.MEDIA).file_url(
207            self.background,
208            request,
209            use_cache=use_cache,
210        )
211
212    def background_themed_urls(
213        self,
214        request: HttpRequest | None = None,
215        use_cache: bool = True,
216    ) -> dict[str, str] | None:
217        """Get themed URLs for background if it contains %(theme)s"""
218        if not self.background:
219            if request:
220                return request.brand.branding_default_flow_background_themed_urls(
221                    request,
222                    use_cache=use_cache,
223                )
224            return None
225
226        return get_file_manager(FileUsage.MEDIA).themed_urls(
227            self.background,
228            request,
229            use_cache=use_cache,
230        )
231
232    stages = models.ManyToManyField(Stage, through="FlowStageBinding", blank=True)
233
234    @property
235    def serializer(self) -> type[BaseSerializer]:
236        from authentik.flows.api.flows import FlowSerializer
237
238        return FlowSerializer
239
240    def __str__(self) -> str:
241        return f"Flow {self.name} ({self.slug})"
242
243    class Meta:
244        verbose_name = _("Flow")
245        verbose_name_plural = _("Flows")
246
247        permissions = [
248            ("export_flow", _("Can export a Flow")),
249            ("inspect_flow", _("Can inspect a Flow's execution")),
250            ("view_flow_cache", _("View Flow's cache metrics")),
251            ("clear_flow_cache", _("Clear Flow's cache metrics")),
252        ]

Flow describes how a series of Stages should be executed to authenticate/enroll/recover a user. Additionally, policies can be applied, to specify which users have access to this flow.

def flow_uuid(unknown):

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

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 slug(unknown):

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

def title(unknown):

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

def layout(unknown):

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

def designation(unknown):

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

def background(unknown):

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

def compatibility_mode(unknown):

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

def denied_action(unknown):

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

def authentication(unknown):

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

def background_url( self, request: django.http.request.HttpRequest | None = None, use_cache: bool = True) -> str:
190    def background_url(
191        self,
192        request: HttpRequest | None = None,
193        use_cache: bool = True,
194    ) -> str:
195        """Get the URL to the background image"""
196        if not self.background:
197            if request:
198                return request.brand.branding_default_flow_background_url(
199                    request,
200                    use_cache=use_cache,
201                )
202            return (
203                CONFIG.get("web.path", "/")[:-1] + "/static/dist/assets/images/flow_background.jpg"
204            )
205
206        return get_file_manager(FileUsage.MEDIA).file_url(
207            self.background,
208            request,
209            use_cache=use_cache,
210        )

Get the URL to the background image

def background_themed_urls( self, request: django.http.request.HttpRequest | None = None, use_cache: bool = True) -> dict[str, str] | None:
212    def background_themed_urls(
213        self,
214        request: HttpRequest | None = None,
215        use_cache: bool = True,
216    ) -> dict[str, str] | None:
217        """Get themed URLs for background if it contains %(theme)s"""
218        if not self.background:
219            if request:
220                return request.brand.branding_default_flow_background_themed_urls(
221                    request,
222                    use_cache=use_cache,
223                )
224            return None
225
226        return get_file_manager(FileUsage.MEDIA).themed_urls(
227            self.background,
228            request,
229            use_cache=use_cache,
230        )

Get themed URLs for background if it contains %(theme)s

stages

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.

serializer: type[rest_framework.serializers.BaseSerializer]
234    @property
235    def serializer(self) -> type[BaseSerializer]:
236        from authentik.flows.api.flows import FlowSerializer
237
238        return FlowSerializer

Get serializer for this model

def get_layout_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_designation_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_denied_action_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_authentication_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.

policybindingmodel_ptr_id
policybindingmodel_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.

provider_authentication

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.

provider_authorization

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.

provider_invalidation

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.

source_authentication

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.

source_enrollment

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.

flowstagebinding_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.

flowtoken_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.

brand_authentication

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.

brand_invalidation

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.

brand_recovery

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.

brand_unenrollment

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.

brand_user_settings

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.

brand_device_code

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.

brand_lockdown

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.

agentconnector_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.

invitation_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.

passwordstage_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.

source_pre_authentication

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.

authenticatorstaticstage_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.

authenticatorduostage_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.

authenticatoremailstage_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.

authenticatorsmsstage_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.

authenticatorwebauthnstage_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.

telegram_source_pre_authentication

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.

authenticatortotpstage_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.

redirectstage_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.

account_lockdown_stages

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.

authenticatorendpointgdtcstage_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.

The requested object does not exist

The query returned multiple objects when only one was expected.

255class FlowStageBinding(SerializerModel, PolicyBindingModel):
256    """Relationship between Flow and Stage. Order is required and unique for
257    each flow-stage Binding. Additionally, policies can be specified, which determine if
258    this Binding applies to the current user"""
259
260    fsb_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4)
261
262    target = models.ForeignKey("Flow", on_delete=models.CASCADE)
263    stage = InheritanceForeignKey(Stage, on_delete=models.CASCADE)
264
265    evaluate_on_plan = models.BooleanField(
266        default=False,
267        help_text=_("Evaluate policies during the Flow planning process."),
268    )
269    re_evaluate_policies = models.BooleanField(
270        default=True,
271        help_text=_("Evaluate policies when the Stage is presented to the user."),
272    )
273
274    invalid_response_action = models.TextField(
275        choices=InvalidResponseAction.choices,
276        default=InvalidResponseAction.RETRY,
277        help_text=_(
278            "Configure how the flow executor should handle an invalid response to a "
279            "challenge. RETRY returns the error message and a similar challenge to the "
280            "executor. RESTART restarts the flow from the beginning, and RESTART_WITH_CONTEXT "
281            "restarts the flow while keeping the current context."
282        ),
283    )
284
285    order = models.IntegerField()
286
287    objects = InheritanceManager()
288
289    @property
290    def serializer(self) -> type[BaseSerializer]:
291        from authentik.flows.api.bindings import FlowStageBindingSerializer
292
293        return FlowStageBindingSerializer
294
295    def __str__(self) -> str:
296        if not self.target_id and self.stage_id:
297            return f"In-memory Flow-stage binding {self.stage}"
298        return f"Flow-stage binding #{self.order} to {self.target_id}"
299
300    class Meta:
301        ordering = ["target", "order"]
302
303        verbose_name = _("Flow Stage Binding")
304        verbose_name_plural = _("Flow Stage Bindings")
305        unique_together = (("target", "stage", "order"),)

Relationship between Flow and Stage. Order is required and unique for each flow-stage Binding. Additionally, policies can be specified, which determine if this Binding applies to the current user

def fsb_uuid(unknown):

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

target

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.

stage

Forward ManyToOne Descriptor that selects subclass. Requires InheritanceAutoManager.

def evaluate_on_plan(unknown):

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

def re_evaluate_policies(unknown):

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

def invalid_response_action(unknown):

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

def order(unknown):

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

def objects(unknown):

The type of the None singleton.

serializer: type[rest_framework.serializers.BaseSerializer]
289    @property
290    def serializer(self) -> type[BaseSerializer]:
291        from authentik.flows.api.bindings import FlowStageBindingSerializer
292
293        return FlowStageBindingSerializer

Get serializer for this model

target_id
stage_id
def get_invalid_response_action_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.

policybindingmodel_ptr_id
policybindingmodel_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 FlowStageBinding.DoesNotExist(authentik.policies.models.PolicyBindingModel.DoesNotExist):

The requested object does not exist

class FlowStageBinding.MultipleObjectsReturned(authentik.policies.models.PolicyBindingModel.MultipleObjectsReturned):

The query returned multiple objects when only one was expected.

class ConfigurableStage(django.db.models.base.Model):
308class ConfigurableStage(models.Model):
309    """Abstract base class for a Stage that can be configured by the enduser.
310    The stage should create a default flow with the configure_stage designation during
311    migration."""
312
313    configure_flow = models.ForeignKey(
314        Flow,
315        on_delete=models.SET_NULL,
316        null=True,
317        blank=True,
318        help_text=_(
319            "Flow used by an authenticated user to configure this Stage. "
320            "If empty, user will not be able to configure this stage."
321        ),
322    )
323
324    class Meta:
325        abstract = True

Abstract base class for a Stage that can be configured by the enduser. The stage should create a default flow with the configure_stage designation during migration.

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.

configure_flow_id
class ConfigurableStage.Meta:
324    class Meta:
325        abstract = True
abstract = False
class FriendlyNamedStage(django.db.models.base.Model):
328class FriendlyNamedStage(models.Model):
329    """Abstract base class for a Stage that can have a user friendly name configured."""
330
331    friendly_name = models.TextField(blank=True)
332
333    class Meta:
334        abstract = True

Abstract base class for a Stage that can have a user friendly name configured.

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.

class FriendlyNamedStage.Meta:
333    class Meta:
334        abstract = True
abstract = False
337class FlowToken(InternallyManagedMixin, Token):
338    """Subclass of a standard Token, stores the currently active flow plan upon creation.
339    Can be used to later resume a flow."""
340
341    flow = models.ForeignKey(Flow, on_delete=models.CASCADE)
342    _plan = models.TextField()
343    revoke_on_execution = models.BooleanField(default=True)
344
345    @staticmethod
346    def pickle(plan: FlowPlan) -> str:
347        """Pickle into string"""
348        data = dumps(plan)
349        return b64encode(data).decode()
350
351    @property
352    def plan(self) -> FlowPlan:
353        """Load Flow plan from pickled version"""
354        return loads(b64decode(self._plan.encode()))  # nosec
355
356    def __str__(self) -> str:
357        return f"Flow Token {super().__str__()}"
358
359    class Meta:
360        verbose_name = _("Flow Token")
361        verbose_name_plural = _("Flow Tokens")

Subclass of a standard Token, stores the currently active flow plan upon creation. Can be used to later resume a flow.

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 revoke_on_execution(unknown):

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

@staticmethod
def pickle(unknown):
345    @staticmethod
346    def pickle(plan: FlowPlan) -> str:
347        """Pickle into string"""
348        data = dumps(plan)
349        return b64encode(data).decode()

Pickle into string

plan
351    @property
352    def plan(self) -> FlowPlan:
353        """Load Flow plan from pickled version"""
354        return loads(b64decode(self._plan.encode()))  # nosec

Load Flow plan from pickled version

flow_id
token_ptr_id
token_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 FlowToken.DoesNotExist(authentik.core.models.Token.DoesNotExist):

The requested object does not exist

class FlowToken.MultipleObjectsReturned(authentik.core.models.Token.MultipleObjectsReturned):

The query returned multiple objects when only one was expected.