authentik.core.models

authentik core models

   1"""authentik core models"""
   2
   3import re
   4import traceback
   5from datetime import datetime
   6from enum import StrEnum
   7from hashlib import sha256
   8from typing import Any, Self
   9from uuid import uuid4
  10
  11import pgtrigger
  12from deepmerge import always_merger
  13from django.contrib.auth.hashers import check_password
  14from django.contrib.auth.models import AbstractUser, Permission
  15from django.contrib.auth.models import UserManager as DjangoUserManager
  16from django.contrib.sessions.base_session import AbstractBaseSession
  17from django.core.validators import validate_slug
  18from django.db import models
  19from django.db.models import Manager, Q, QuerySet, options
  20from django.http import HttpRequest
  21from django.utils.functional import cached_property
  22from django.utils.timezone import now
  23from django.utils.translation import gettext_lazy as _
  24from guardian.conf import settings
  25from guardian.models import RoleModelPermission, RoleObjectPermission
  26from model_utils.managers import InheritanceManager
  27from psqlextra.indexes import UniqueIndex
  28from psqlextra.models import PostgresMaterializedViewModel
  29from rest_framework.serializers import Serializer
  30from structlog.stdlib import get_logger
  31
  32from authentik.admin.files.fields import FileField
  33from authentik.admin.files.manager import get_file_manager
  34from authentik.admin.files.usage import FileUsage
  35from authentik.blueprints.models import ManagedModel
  36from authentik.core.expression.exceptions import PropertyMappingExpressionException
  37from authentik.core.types import UILoginButton, UserSettingSerializer
  38from authentik.lib.avatars import get_avatar
  39from authentik.lib.expression.exceptions import ControlFlowException
  40from authentik.lib.generators import generate_id
  41from authentik.lib.merge import MERGE_LIST_UNIQUE
  42from authentik.lib.models import (
  43    CreatedUpdatedModel,
  44    DomainlessFormattedURLValidator,
  45    SerializerModel,
  46)
  47from authentik.lib.utils.inheritance import get_deepest_child
  48from authentik.lib.utils.reflection import class_to_path
  49from authentik.lib.utils.time import timedelta_from_string
  50from authentik.policies.models import PolicyBindingModel
  51from authentik.rbac.models import Role
  52from authentik.tenants.models import DEFAULT_TOKEN_DURATION, DEFAULT_TOKEN_LENGTH
  53from authentik.tenants.utils import get_current_tenant, get_unique_identifier
  54
  55LOGGER = get_logger()
  56USERNAME_MAX_LENGTH = 150
  57USER_PATH_SYSTEM_PREFIX = "goauthentik.io"
  58_USER_ATTR_PREFIX = f"{USER_PATH_SYSTEM_PREFIX}/user"
  59USER_ATTRIBUTE_DEBUG = f"{_USER_ATTR_PREFIX}/debug"
  60USER_ATTRIBUTE_GENERATED = f"{_USER_ATTR_PREFIX}/generated"
  61USER_ATTRIBUTE_EXPIRES = f"{_USER_ATTR_PREFIX}/expires"
  62USER_ATTRIBUTE_DELETE_ON_LOGOUT = f"{_USER_ATTR_PREFIX}/delete-on-logout"
  63USER_ATTRIBUTE_SOURCES = f"{_USER_ATTR_PREFIX}/sources"
  64USER_ATTRIBUTE_TOKEN_EXPIRING = f"{_USER_ATTR_PREFIX}/token-expires"  # nosec
  65USER_ATTRIBUTE_TOKEN_MAXIMUM_LIFETIME = f"{_USER_ATTR_PREFIX}/token-maximum-lifetime"  # nosec
  66USER_ATTRIBUTE_CHANGE_USERNAME = f"{_USER_ATTR_PREFIX}/can-change-username"
  67USER_ATTRIBUTE_CHANGE_NAME = f"{_USER_ATTR_PREFIX}/can-change-name"
  68USER_ATTRIBUTE_CHANGE_EMAIL = f"{_USER_ATTR_PREFIX}/can-change-email"
  69USER_PATH_SERVICE_ACCOUNT = f"{USER_PATH_SYSTEM_PREFIX}/service-accounts"
  70
  71options.DEFAULT_NAMES = options.DEFAULT_NAMES + (
  72    # used_by API that allows models to specify if they shadow an object
  73    # for example the proxy provider which is built on top of an oauth provider
  74    "authentik_used_by_shadows",
  75)
  76
  77GROUP_RECURSION_LIMIT = 20
  78
  79MANAGED_ROLE_PREFIX_USER = "ak-managed-role--user"
  80MANAGED_ROLE_PREFIX_GROUP = "ak-managed-role--group"
  81
  82
  83def managed_role_name(user_or_group: models.Model):
  84    if isinstance(user_or_group, User):
  85        return f"{MANAGED_ROLE_PREFIX_USER}-{user_or_group.pk}"
  86    if isinstance(user_or_group, Group):
  87        return f"{MANAGED_ROLE_PREFIX_GROUP}-{user_or_group.pk}"
  88    raise TypeError("Managed roles are only available for User or Group.")
  89
  90
  91def default_token_duration() -> datetime:
  92    """Default duration a Token is valid"""
  93    current_tenant = get_current_tenant()
  94    token_duration = (
  95        current_tenant.default_token_duration
  96        if hasattr(current_tenant, "default_token_duration")
  97        else DEFAULT_TOKEN_DURATION
  98    )
  99    return now() + timedelta_from_string(token_duration)
 100
 101
 102def default_token_key() -> str:
 103    """Default token key"""
 104    current_tenant = get_current_tenant()
 105    token_length = (
 106        current_tenant.default_token_length
 107        if hasattr(current_tenant, "default_token_length")
 108        else DEFAULT_TOKEN_LENGTH
 109    )
 110    # We use generate_id since the chars in the key should be easy
 111    # to use in Emails (for verification) and URLs (for recovery)
 112    return generate_id(token_length)
 113
 114
 115class UserTypes(models.TextChoices):
 116    """User types, both for grouping, licensing and permissions in the case
 117    of the internal_service_account"""
 118
 119    INTERNAL = "internal"
 120    EXTERNAL = "external"
 121
 122    # User-created service accounts
 123    SERVICE_ACCOUNT = "service_account"
 124
 125    # Special user type for internally managed and created service
 126    # accounts, such as outpost users
 127    INTERNAL_SERVICE_ACCOUNT = "internal_service_account"
 128
 129
 130class AttributesMixin(models.Model):
 131    """Adds an attributes property to a model"""
 132
 133    attributes = models.JSONField(default=dict, blank=True)
 134
 135    class Meta:
 136        abstract = True
 137
 138    def update_attributes(self, properties: dict[str, Any]):
 139        """Update fields and attributes, but correctly by merging dicts"""
 140        needs_update = False
 141        for key, value in properties.items():
 142            if key == "attributes":
 143                continue
 144            if getattr(self, key, None) != value:
 145                setattr(self, key, value)
 146                needs_update = True
 147        final_attributes = {}
 148        MERGE_LIST_UNIQUE.merge(final_attributes, self.attributes)
 149        MERGE_LIST_UNIQUE.merge(final_attributes, properties.get("attributes", {}))
 150        if self.attributes != final_attributes:
 151            self.attributes = final_attributes
 152            needs_update = True
 153        if needs_update:
 154            self.save()
 155
 156    @classmethod
 157    def update_or_create_attributes(
 158        cls, query: dict[str, Any], properties: dict[str, Any]
 159    ) -> tuple[Self, bool]:
 160        """Same as django's update_or_create but correctly updates attributes by merging dicts"""
 161        instance = cls.objects.filter(**query).first()
 162        if not instance:
 163            return cls.objects.create(**properties), True
 164        instance.update_attributes(properties)
 165        return instance, False
 166
 167
 168class GroupQuerySet(QuerySet):
 169    def with_descendants(self):
 170        pks = self.values_list("pk", flat=True)
 171        return Group.objects.filter(Q(pk__in=pks) | Q(ancestor_nodes__ancestor__in=pks)).distinct()
 172
 173    def with_ancestors(self):
 174        pks = self.values_list("pk", flat=True)
 175        return Group.objects.filter(
 176            Q(pk__in=pks) | Q(descendant_nodes__descendant__in=pks)
 177        ).distinct()
 178
 179
 180class Group(SerializerModel, AttributesMixin):
 181    """Group model which supports a hierarchy and has attributes"""
 182
 183    group_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4)
 184
 185    name = models.TextField(verbose_name=_("name"), unique=True)
 186    is_superuser = models.BooleanField(
 187        default=False, help_text=_("Users added to this group will be superusers.")
 188    )
 189
 190    roles = models.ManyToManyField("authentik_rbac.Role", related_name="groups", blank=True)
 191
 192    parents = models.ManyToManyField(
 193        "Group",
 194        blank=True,
 195        symmetrical=False,
 196        through="GroupParentageNode",
 197        related_name="children",
 198    )
 199
 200    objects = GroupQuerySet.as_manager()
 201
 202    class Meta:
 203        indexes = (
 204            models.Index(fields=["name"]),
 205            models.Index(fields=["is_superuser"]),
 206        )
 207        verbose_name = _("Group")
 208        verbose_name_plural = _("Groups")
 209        permissions = [
 210            ("add_user_to_group", _("Add user to group")),
 211            ("remove_user_from_group", _("Remove user from group")),
 212            ("enable_group_superuser", _("Enable superuser status")),
 213            ("disable_group_superuser", _("Disable superuser status")),
 214        ]
 215
 216    def __str__(self):
 217        return f"Group {self.name}"
 218
 219    @property
 220    def serializer(self) -> Serializer:
 221        from authentik.core.api.groups import GroupSerializer
 222
 223        return GroupSerializer
 224
 225    @property
 226    def num_pk(self) -> int:
 227        """Get a numerical, int32 ID for the group"""
 228        # int max is 2147483647 (10 digits) so 9 is the max usable
 229        # in the LDAP Outpost we use the last 5 chars so match here
 230        return int(str(self.pk.int)[:5])
 231
 232    def is_member(self, user: User) -> bool:
 233        """Recursively check if `user` is member of us, or any parent."""
 234        return user.all_groups().filter(group_uuid=self.group_uuid).exists()
 235
 236    def all_roles(self) -> QuerySet[Role]:
 237        """Get all roles of this group and all of its ancestors."""
 238        return Role.objects.filter(
 239            groups__in=Group.objects.filter(pk=self.pk).with_ancestors()
 240        ).distinct()
 241
 242    def get_managed_role(self, create=False):
 243        if create:
 244            name = managed_role_name(self)
 245            role, created = Role.objects.get_or_create(name=name, managed=name)
 246            if created:
 247                role.groups.add(self)
 248            return role
 249        else:
 250            return Role.objects.filter(name=managed_role_name(self)).first()
 251
 252    def assign_perms_to_managed_role(
 253        self,
 254        perms: str | list[str] | Permission | list[Permission],
 255        obj: models.Model | None = None,
 256    ):
 257        if not perms:
 258            return
 259        role = self.get_managed_role(create=True)
 260        role.assign_perms(perms, obj)
 261
 262
 263class GroupParentageNode(models.Model):
 264    uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4)
 265
 266    child = models.ForeignKey(Group, related_name="parent_nodes", on_delete=models.CASCADE)
 267    parent = models.ForeignKey(Group, related_name="child_nodes", on_delete=models.CASCADE)
 268
 269    class Meta:
 270        verbose_name = _("Group Parentage Node")
 271        verbose_name_plural = _("Group Parentage Nodes")
 272
 273        db_table = "authentik_core_groupparentage"
 274
 275        triggers = [
 276            pgtrigger.Trigger(
 277                name="refresh_groupancestry",
 278                operation=pgtrigger.Insert | pgtrigger.Update | pgtrigger.Delete,
 279                when=pgtrigger.After,
 280                func="""
 281                    REFRESH MATERIALIZED VIEW CONCURRENTLY authentik_core_groupancestry;
 282                    RETURN NULL;
 283                """,
 284            ),
 285        ]
 286
 287    def __str__(self) -> str:
 288        return f"Group Parentage Node from #{self.child_id} to {self.parent_id}"
 289
 290
 291class GroupAncestryNode(PostgresMaterializedViewModel):
 292    descendant = models.ForeignKey(
 293        Group, related_name="ancestor_nodes", on_delete=models.DO_NOTHING
 294    )
 295    ancestor = models.ForeignKey(
 296        Group, related_name="descendant_nodes", on_delete=models.DO_NOTHING
 297    )
 298
 299    class Meta:
 300        # This is a transitive closure of authentik_core_groupparentage
 301        # See https://en.wikipedia.org/wiki/Transitive_closure#In_graph_theory
 302        db_table = "authentik_core_groupancestry"
 303        indexes = [
 304            models.Index(fields=["descendant"]),
 305            models.Index(fields=["ancestor"]),
 306            UniqueIndex(fields=["id"]),
 307        ]
 308
 309    class ViewMeta:
 310        query = """
 311            WITH RECURSIVE accumulator AS (
 312                SELECT
 313                child_id::text || '-' || parent_id::text as id,
 314                child_id AS descendant_id,
 315                parent_id AS ancestor_id
 316                FROM authentik_core_groupparentage
 317
 318                UNION
 319
 320                SELECT
 321                accumulator.descendant_id::text || '-' || current.parent_id::text as id,
 322                accumulator.descendant_id,
 323                current.parent_id AS ancestor_id
 324                FROM accumulator
 325                JOIN authentik_core_groupparentage current
 326                ON accumulator.ancestor_id = current.child_id
 327            )
 328            SELECT * FROM accumulator
 329        """
 330
 331    def __str__(self) -> str:
 332        return f"Group Ancestry Node from {self.descendant_id} to {self.ancestor_id}"
 333
 334
 335class UserQuerySet(models.QuerySet):
 336    """User queryset"""
 337
 338    def exclude_anonymous(self):
 339        """Exclude anonymous user"""
 340        return self.exclude(**{User.USERNAME_FIELD: settings.ANONYMOUS_USER_NAME})
 341
 342
 343class UserManager(DjangoUserManager):
 344    """User manager that doesn't assign is_superuser and is_staff"""
 345
 346    def get_queryset(self):
 347        """Create special user queryset"""
 348        return UserQuerySet(self.model, using=self._db)
 349
 350    def create_user(self, username, email=None, password=None, **extra_fields):
 351        """User manager that doesn't assign is_superuser and is_staff"""
 352        return self._create_user(username, email, password, **extra_fields)
 353
 354    def exclude_anonymous(self) -> QuerySet:
 355        """Exclude anonymous user"""
 356        return self.get_queryset().exclude_anonymous()
 357
 358
 359class User(SerializerModel, AttributesMixin, AbstractUser):
 360    """authentik User model, based on django's contrib auth user model."""
 361
 362    # Overwriting PermissionsMixin: permissions are handled by roles.
 363    # (This knowingly violates the Liskov substitution principle. It is better to fail loudly.)
 364    user_permissions = None
 365
 366    uuid = models.UUIDField(default=uuid4, editable=False, unique=True)
 367    name = models.TextField(help_text=_("User's display name."))
 368    path = models.TextField(default="users")
 369    type = models.TextField(choices=UserTypes.choices, default=UserTypes.INTERNAL)
 370
 371    sources = models.ManyToManyField("Source", through="UserSourceConnection")
 372    groups = models.ManyToManyField("Group", related_name="users")
 373    roles = models.ManyToManyField("authentik_rbac.Role", related_name="users", blank=True)
 374    password_change_date = models.DateTimeField(auto_now_add=True)
 375
 376    last_updated = models.DateTimeField(auto_now=True)
 377
 378    objects = UserManager()
 379
 380    class Meta:
 381        verbose_name = _("User")
 382        verbose_name_plural = _("Users")
 383        permissions = [
 384            ("reset_user_password", _("Reset Password")),
 385            ("impersonate", _("Can impersonate other users")),
 386            ("preview_user", _("Can preview user data sent to providers")),
 387            ("view_user_applications", _("View applications the user has access to")),
 388        ]
 389        indexes = [
 390            models.Index(fields=["last_login"]),
 391            models.Index(fields=["password_change_date"]),
 392            models.Index(fields=["uuid"]),
 393            models.Index(fields=["path"]),
 394            models.Index(fields=["type"]),
 395            models.Index(fields=["date_joined"]),
 396            models.Index(fields=["last_updated"]),
 397        ]
 398
 399    def __str__(self):
 400        return self.username
 401
 402    @staticmethod
 403    def default_path() -> str:
 404        """Get the default user path"""
 405        return User._meta.get_field("path").default
 406
 407    def all_groups(self) -> QuerySet[Group]:
 408        """Recursively get all groups this user is a member of."""
 409        return self.groups.all().with_ancestors()
 410
 411    def all_roles(self) -> QuerySet[Role]:
 412        """Get all roles of this user and all of its groups (recursively)."""
 413        return Role.objects.filter(Q(users=self) | Q(groups__in=self.all_groups())).distinct()
 414
 415    def get_managed_role(self, create=False):
 416        if create:
 417            name = managed_role_name(self)
 418            role, created = Role.objects.get_or_create(name=name, managed=name)
 419            if created:
 420                role.users.add(self)
 421            return role
 422        else:
 423            return Role.objects.filter(name=managed_role_name(self)).first()
 424
 425    def get_all_model_perms_on_managed_role(self) -> QuerySet[RoleModelPermission]:
 426        role = self.get_managed_role()
 427        if not role:
 428            return RoleModelPermission.objects.none()
 429        return RoleModelPermission.objects.filter(role=role)
 430
 431    def get_all_obj_perms_on_managed_role(self) -> QuerySet[RoleObjectPermission]:
 432        role = self.get_managed_role()
 433        if not role:
 434            return RoleObjectPermission.objects.none()
 435        return RoleObjectPermission.objects.filter(role=role)
 436
 437    def assign_perms_to_managed_role(
 438        self,
 439        perms: str | list[str] | Permission | list[Permission],
 440        obj: models.Model | None = None,
 441    ):
 442        if not perms:
 443            return
 444        role = self.get_managed_role(create=True)
 445        role.assign_perms(perms, obj)
 446
 447    def remove_perms_from_managed_role(
 448        self,
 449        perms: str | list[str] | Permission | list[Permission],
 450        obj: models.Model | None = None,
 451    ):
 452        role = self.get_managed_role()
 453        if not role:
 454            return None
 455        role.remove_perms(perms, obj)
 456
 457    def remove_all_perms_from_managed_role(self):
 458        role = self.get_managed_role()
 459        if not role:
 460            return None
 461        RoleModelPermission.objects.filter(role=role).delete()
 462        RoleObjectPermission.objects.filter(role=role).delete()
 463
 464    def group_attributes(self, request: HttpRequest | None = None) -> dict[str, Any]:
 465        """Get a dictionary containing the attributes from all groups the user belongs to,
 466        including the users attributes"""
 467        final_attributes = {}
 468        if request and hasattr(request, "brand"):
 469            always_merger.merge(final_attributes, request.brand.attributes)
 470        for group in self.all_groups().order_by("name"):
 471            always_merger.merge(final_attributes, group.attributes)
 472        always_merger.merge(final_attributes, self.attributes)
 473        return final_attributes
 474
 475    def app_entitlements(self, app: Application | None) -> QuerySet[ApplicationEntitlement]:
 476        """Get all entitlements this user has for `app`."""
 477        if not app:
 478            return []
 479        all_groups = self.all_groups()
 480        qs = app.applicationentitlement_set.filter(
 481            Q(
 482                Q(bindings__user=self) | Q(bindings__group__in=all_groups),
 483                bindings__negate=False,
 484            )
 485            | Q(
 486                Q(~Q(bindings__user=self), bindings__user__isnull=False)
 487                | Q(~Q(bindings__group__in=all_groups), bindings__group__isnull=False),
 488                bindings__negate=True,
 489            ),
 490            bindings__enabled=True,
 491        ).order_by("name")
 492        return qs
 493
 494    def app_entitlements_attributes(self, app: Application | None) -> dict:
 495        """Get a dictionary containing all merged attributes from app entitlements for `app`."""
 496        final_attributes = {}
 497        for attrs in self.app_entitlements(app).values_list("attributes", flat=True):
 498            always_merger.merge(final_attributes, attrs)
 499        return final_attributes
 500
 501    @property
 502    def serializer(self) -> Serializer:
 503        from authentik.core.api.users import UserSerializer
 504
 505        return UserSerializer
 506
 507    @cached_property
 508    def is_superuser(self) -> bool:
 509        """Get supseruser status based on membership in a group with superuser status"""
 510        return self.all_groups().filter(is_superuser=True).exists()
 511
 512    @property
 513    def is_staff(self) -> bool:
 514        """superuser == staff user"""
 515        return self.is_superuser  # type: ignore
 516
 517    # TODO: remove this after 2026.
 518    @property
 519    def ak_groups(self):
 520        """This is a proxy for a renamed, deprecated field."""
 521        from authentik.events.models import Event
 522
 523        deprecation = "authentik.core.models.User.ak_groups"
 524        replacement = "authentik.core.models.User.groups"
 525        message_logger = (
 526            f"{deprecation} is deprecated and will be removed in a future version of "
 527            f"authentik. Please use {replacement} instead."
 528        )
 529        message_event = (
 530            f"{message_logger} This event will not be repeated until it expires (by "
 531            "default: in 30 days). See authentik logs for every will invocation of this "
 532            "deprecation."
 533        )
 534        stacktrace = traceback.format_stack()
 535        # The last line is this function, the next-to-last line is its caller
 536        cause = stacktrace[-2] if len(stacktrace) > 1 else "Unknown, see stacktrace in logs"
 537        if search := re.search(r'"(.*?)"', cause):
 538            cause = f"Property mapping or Expression policy named {search.group(1)}"
 539
 540        LOGGER.warning(
 541            "deprecation used",
 542            message=message_logger,
 543            deprecation=deprecation,
 544            replacement=replacement,
 545            cause=cause,
 546            stacktrace=stacktrace,
 547        )
 548        Event.log_deprecation(
 549            deprecation, message=message_event, cause=cause, replacement=replacement
 550        )
 551        return self.groups
 552
 553    def set_password(self, raw_password, signal=True, sender=None, request=None):
 554        if self.pk and signal:
 555            from authentik.core.signals import password_changed
 556
 557            if not sender:
 558                sender = self
 559            password_changed.send(sender=sender, user=self, password=raw_password, request=request)
 560        self.password_change_date = now()
 561        return super().set_password(raw_password)
 562
 563    def check_password(self, raw_password: str) -> bool:
 564        """
 565        Return a boolean of whether the raw_password was correct. Handles
 566        hashing formats behind the scenes.
 567
 568        Slightly changed version which doesn't send a signal for such internal hash upgrades
 569        """
 570
 571        def setter(raw_password):
 572            self.set_password(raw_password, signal=False)
 573            # Password hash upgrades shouldn't be considered password changes.
 574            self._password = None
 575            self.save(update_fields=["password"])
 576
 577        return check_password(raw_password, self.password, setter)
 578
 579    @property
 580    def uid(self) -> str:
 581        """Generate a globally unique UID, based on the user ID and the hashed secret key"""
 582        return sha256(f"{self.id}-{get_unique_identifier()}".encode("ascii")).hexdigest()
 583
 584    def locale(self, request: HttpRequest | None = None) -> str:
 585        """Get the locale the user has configured"""
 586        if request and hasattr(request, "LANGUAGE_CODE"):
 587            return request.LANGUAGE_CODE
 588        try:
 589            return self.attributes.get("settings", {}).get("locale", "")
 590
 591        except Exception as exc:  # noqa
 592            LOGGER.warning("Failed to get default locale", exc=exc)
 593        if request:
 594            return request.brand.locale
 595        return ""
 596
 597    @property
 598    def avatar(self) -> str:
 599        """Get avatar, depending on authentik.avatar setting"""
 600        return get_avatar(self)
 601
 602
 603class Provider(SerializerModel):
 604    """Application-independent Provider instance. For example SAML2 Remote, OAuth2 Application"""
 605
 606    name = models.TextField(unique=True)
 607
 608    authentication_flow = models.ForeignKey(
 609        "authentik_flows.Flow",
 610        null=True,
 611        on_delete=models.SET_NULL,
 612        help_text=_(
 613            "Flow used for authentication when the associated application is accessed by an "
 614            "un-authenticated user."
 615        ),
 616        related_name="provider_authentication",
 617    )
 618    authorization_flow = models.ForeignKey(
 619        "authentik_flows.Flow",
 620        # Set to cascade even though null is allowed, since most providers
 621        # still require an authorization flow set
 622        on_delete=models.CASCADE,
 623        null=True,
 624        help_text=_("Flow used when authorizing this provider."),
 625        related_name="provider_authorization",
 626    )
 627    invalidation_flow = models.ForeignKey(
 628        "authentik_flows.Flow",
 629        on_delete=models.SET_DEFAULT,
 630        default=None,
 631        null=True,
 632        help_text=_("Flow used ending the session from a provider."),
 633        related_name="provider_invalidation",
 634    )
 635
 636    property_mappings = models.ManyToManyField("PropertyMapping", default=None, blank=True)
 637
 638    backchannel_application = models.ForeignKey(
 639        "Application",
 640        default=None,
 641        null=True,
 642        on_delete=models.CASCADE,
 643        help_text=_(
 644            "Accessed from applications; optional backchannel providers for protocols "
 645            "like LDAP and SCIM."
 646        ),
 647        related_name="backchannel_providers",
 648    )
 649
 650    is_backchannel = models.BooleanField(default=False)
 651
 652    objects = InheritanceManager()
 653
 654    @property
 655    def launch_url(self) -> str | None:
 656        """URL to this provider and initiate authorization for the user.
 657        Can return None for providers that are not URL-based"""
 658        return None
 659
 660    @property
 661    def icon_url(self) -> str | None:
 662        return None
 663
 664    @property
 665    def component(self) -> str:
 666        """Return component used to edit this object"""
 667        raise NotImplementedError
 668
 669    @property
 670    def serializer(self) -> type[Serializer]:
 671        """Get serializer for this model"""
 672        raise NotImplementedError
 673
 674    def __str__(self):
 675        return str(self.name)
 676
 677
 678class BackchannelProvider(Provider):
 679    """Base class for providers that augment other providers, for example LDAP and SCIM.
 680    Multiple of these providers can be configured per application, they may not use the application
 681    slug in URLs as an application may have multiple instances of the same
 682    type of Backchannel provider
 683
 684    They can use the application's policies and metadata"""
 685
 686    @property
 687    def component(self) -> str:
 688        raise NotImplementedError
 689
 690    @property
 691    def serializer(self) -> type[Serializer]:
 692        raise NotImplementedError
 693
 694    class Meta:
 695        abstract = True
 696
 697
 698class ApplicationQuerySet(QuerySet):
 699    def with_provider(self) -> QuerySet[Application]:
 700        qs = self.select_related("provider")
 701        for subclass in Provider.objects.get_queryset()._get_subclasses_recurse(Provider):
 702            qs = qs.select_related(f"provider__{subclass}")
 703            # Also prefetch/select through each subclass path to ensure casted instances have access
 704            qs = qs.prefetch_related(f"provider__{subclass}__property_mappings")
 705            qs = qs.select_related(f"provider__{subclass}__application")
 706            qs = qs.select_related(f"provider__{subclass}__backchannel_application")
 707        return qs
 708
 709
 710class Application(SerializerModel, PolicyBindingModel):
 711    """Every Application which uses authentik for authentication/identification/authorization
 712    needs an Application record. Other authentication types can subclass this Model to
 713    add custom fields and other properties"""
 714
 715    name = models.TextField(help_text=_("Application's display Name."))
 716    slug = models.TextField(
 717        validators=[validate_slug],
 718        help_text=_("Internal application name, used in URLs."),
 719        unique=True,
 720    )
 721    group = models.TextField(blank=True, default="")
 722
 723    provider = models.OneToOneField(
 724        "Provider", null=True, blank=True, default=None, on_delete=models.SET_DEFAULT
 725    )
 726
 727    meta_launch_url = models.TextField(
 728        default="", blank=True, validators=[DomainlessFormattedURLValidator()]
 729    )
 730
 731    open_in_new_tab = models.BooleanField(
 732        default=False, help_text=_("Open launch URL in a new browser tab or window.")
 733    )
 734
 735    meta_icon = FileField(default="", blank=True)
 736    meta_description = models.TextField(default="", blank=True)
 737    meta_publisher = models.TextField(default="", blank=True)
 738
 739    objects = ApplicationQuerySet.as_manager()
 740
 741    # Reserved slugs that would clash with OAuth2 provider endpoints
 742    reserved_slugs = ["authorize", "token", "device", "userinfo", "introspect", "revoke"]
 743
 744    @property
 745    def serializer(self) -> Serializer:
 746        from authentik.core.api.applications import ApplicationSerializer
 747
 748        return ApplicationSerializer
 749
 750    @property
 751    def get_meta_icon(self) -> str | None:
 752        """Get the URL to the App Icon image"""
 753        if not self.meta_icon:
 754            return None
 755
 756        return get_file_manager(FileUsage.MEDIA).file_url(self.meta_icon)
 757
 758    @property
 759    def get_meta_icon_themed_urls(self) -> dict[str, str] | None:
 760        """Get themed URLs for meta_icon if it contains %(theme)s"""
 761        if not self.meta_icon:
 762            return None
 763
 764        return get_file_manager(FileUsage.MEDIA).themed_urls(self.meta_icon)
 765
 766    def get_launch_url(self, user: User | None = None, user_data: dict | None = None) -> str | None:
 767        """Get launch URL if set, otherwise attempt to get launch URL based on provider.
 768
 769        Args:
 770            user: User instance for formatting the URL
 771            user_data: Pre-serialized user data to avoid re-serialization (performance optimization)
 772        """
 773        from authentik.core.api.users import UserSerializer
 774
 775        url = None
 776        if self.meta_launch_url:
 777            url = self.meta_launch_url
 778        elif provider := self.get_provider():
 779            url = provider.launch_url
 780        if user and url:
 781            try:
 782                # Use pre-serialized data if available, otherwise serialize now
 783                if user_data is None:
 784                    user_data = UserSerializer(instance=user).data
 785                return url % user_data
 786            except Exception as exc:  # noqa
 787                LOGGER.warning("Failed to format launch url", exc=exc)
 788                return url
 789        return url
 790
 791    def get_provider(self) -> Provider | None:
 792        """Get casted provider instance. Needs Application queryset with_provider"""
 793        if not self.provider:
 794            return None
 795        return get_deepest_child(self.provider)
 796
 797    def backchannel_provider_for[T: Provider](self, provider_type: type[T], **kwargs) -> T | None:
 798        """Get Backchannel provider for a specific type"""
 799        providers = self.backchannel_providers.filter(
 800            **{f"{provider_type._meta.model_name}__isnull": False},
 801            **kwargs,
 802        )
 803        return getattr(providers.first(), provider_type._meta.model_name)
 804
 805    def __str__(self):
 806        return str(self.name)
 807
 808    class Meta:
 809        verbose_name = _("Application")
 810        verbose_name_plural = _("Applications")
 811
 812
 813class ApplicationEntitlement(AttributesMixin, SerializerModel, PolicyBindingModel):
 814    """Application-scoped entitlement to control authorization in an application"""
 815
 816    name = models.TextField()
 817
 818    app = models.ForeignKey(Application, on_delete=models.CASCADE)
 819
 820    class Meta:
 821        verbose_name = _("Application Entitlement")
 822        verbose_name_plural = _("Application Entitlements")
 823        unique_together = (("app", "name"),)
 824
 825    def __str__(self):
 826        return f"Application Entitlement {self.name} for app {self.app_id}"
 827
 828    @property
 829    def serializer(self) -> type[Serializer]:
 830        from authentik.core.api.application_entitlements import ApplicationEntitlementSerializer
 831
 832        return ApplicationEntitlementSerializer
 833
 834    def supported_policy_binding_targets(self):
 835        return ["group", "user"]
 836
 837
 838class SourceUserMatchingModes(models.TextChoices):
 839    """Different modes a source can handle new/returning users"""
 840
 841    IDENTIFIER = "identifier", _("Use the source-specific identifier")
 842    EMAIL_LINK = (
 843        "email_link",
 844        _(
 845            "Link to a user with identical email address. Can have security implications "
 846            "when a source doesn't validate email addresses."
 847        ),
 848    )
 849    EMAIL_DENY = (
 850        "email_deny",
 851        _(
 852            "Use the user's email address, but deny enrollment when the email address already "
 853            "exists."
 854        ),
 855    )
 856    USERNAME_LINK = (
 857        "username_link",
 858        _(
 859            "Link to a user with identical username. Can have security implications "
 860            "when a username is used with another source."
 861        ),
 862    )
 863    USERNAME_DENY = (
 864        "username_deny",
 865        _("Use the user's username, but deny enrollment when the username already exists."),
 866    )
 867
 868
 869class SourceGroupMatchingModes(models.TextChoices):
 870    """Different modes a source can handle new/returning groups"""
 871
 872    IDENTIFIER = "identifier", _("Use the source-specific identifier")
 873    NAME_LINK = (
 874        "name_link",
 875        _(
 876            "Link to a group with identical name. Can have security implications "
 877            "when a group name is used with another source."
 878        ),
 879    )
 880    NAME_DENY = (
 881        "name_deny",
 882        _("Use the group name, but deny enrollment when the name already exists."),
 883    )
 884
 885
 886class Source(ManagedModel, SerializerModel, PolicyBindingModel):
 887    """Base Authentication source, i.e. an OAuth Provider, SAML Remote or LDAP Server"""
 888
 889    MANAGED_INBUILT = "goauthentik.io/sources/inbuilt"
 890
 891    name = models.TextField(help_text=_("Source's display Name."))
 892    slug = models.TextField(
 893        validators=[validate_slug],
 894        help_text=_("Internal source name, used in URLs."),
 895        unique=True,
 896    )
 897
 898    user_path_template = models.TextField(default="goauthentik.io/sources/%(slug)s")
 899
 900    enabled = models.BooleanField(default=True)
 901    promoted = models.BooleanField(
 902        default=False,
 903        help_text=_(
 904            "When enabled, this source will be displayed as a prominent button on the "
 905            "login page, instead of a small icon."
 906        ),
 907    )
 908    user_property_mappings = models.ManyToManyField(
 909        "PropertyMapping", default=None, blank=True, related_name="source_userpropertymappings_set"
 910    )
 911    group_property_mappings = models.ManyToManyField(
 912        "PropertyMapping", default=None, blank=True, related_name="source_grouppropertymappings_set"
 913    )
 914
 915    icon = FileField(blank=True, default="")
 916
 917    authentication_flow = models.ForeignKey(
 918        "authentik_flows.Flow",
 919        blank=True,
 920        null=True,
 921        default=None,
 922        on_delete=models.SET_NULL,
 923        help_text=_("Flow to use when authenticating existing users."),
 924        related_name="source_authentication",
 925    )
 926    enrollment_flow = models.ForeignKey(
 927        "authentik_flows.Flow",
 928        blank=True,
 929        null=True,
 930        default=None,
 931        on_delete=models.SET_NULL,
 932        help_text=_("Flow to use when enrolling new users."),
 933        related_name="source_enrollment",
 934    )
 935
 936    user_matching_mode = models.TextField(
 937        choices=SourceUserMatchingModes.choices,
 938        default=SourceUserMatchingModes.IDENTIFIER,
 939        help_text=_(
 940            "How the source determines if an existing user should be authenticated or "
 941            "a new user enrolled."
 942        ),
 943    )
 944    group_matching_mode = models.TextField(
 945        choices=SourceGroupMatchingModes.choices,
 946        default=SourceGroupMatchingModes.IDENTIFIER,
 947        help_text=_(
 948            "How the source determines if an existing group should be used or a new group created."
 949        ),
 950    )
 951
 952    objects = InheritanceManager()
 953
 954    @property
 955    def icon_url(self) -> str | None:
 956        """Get the URL to the source icon"""
 957        if not self.icon:
 958            return None
 959
 960        return get_file_manager(FileUsage.MEDIA).file_url(self.icon)
 961
 962    @property
 963    def icon_themed_urls(self) -> dict[str, str] | None:
 964        """Get themed URLs for icon if it contains %(theme)s"""
 965        if not self.icon:
 966            return None
 967
 968        return get_file_manager(FileUsage.MEDIA).themed_urls(self.icon)
 969
 970    def get_user_path(self) -> str:
 971        """Get user path, fallback to default for formatting errors"""
 972        try:
 973            return self.user_path_template % {
 974                "slug": self.slug,
 975            }
 976
 977        except Exception as exc:  # noqa
 978            LOGGER.warning("Failed to template user path", exc=exc, source=self)
 979            return User.default_path()
 980
 981    @property
 982    def component(self) -> str:
 983        """Return component used to edit this object"""
 984        if self.managed == self.MANAGED_INBUILT:
 985            return ""
 986        raise NotImplementedError
 987
 988    @property
 989    def property_mapping_type(self) -> type[PropertyMapping]:
 990        """Return property mapping type used by this object"""
 991        if self.managed == self.MANAGED_INBUILT:
 992            from authentik.core.models import PropertyMapping
 993
 994            return PropertyMapping
 995        raise NotImplementedError
 996
 997    def ui_login_button(self, request: HttpRequest) -> UILoginButton | None:
 998        """If source uses a http-based flow, return UI Information about the login
 999        button. If source doesn't use http-based flow, return None."""
1000        return None
1001
1002    def ui_user_settings(self) -> UserSettingSerializer | None:
1003        """Entrypoint to integrate with User settings. Can either return None if no
1004        user settings are available, or UserSettingSerializer."""
1005        return None
1006
1007    def get_base_user_properties(self, **kwargs) -> dict[str, Any | dict[str, Any]]:
1008        """Get base properties for a user to build final properties upon."""
1009        if self.managed == self.MANAGED_INBUILT:
1010            return {}
1011        raise NotImplementedError
1012
1013    def get_base_group_properties(self, **kwargs) -> dict[str, Any | dict[str, Any]]:
1014        """Get base properties for a group to build final properties upon."""
1015        if self.managed == self.MANAGED_INBUILT:
1016            return {}
1017        raise NotImplementedError
1018
1019    def __str__(self):
1020        return str(self.name)
1021
1022    class Meta:
1023        indexes = [
1024            models.Index(
1025                fields=[
1026                    "slug",
1027                ]
1028            ),
1029            models.Index(
1030                fields=[
1031                    "name",
1032                ]
1033            ),
1034            models.Index(
1035                fields=[
1036                    "enabled",
1037                ]
1038            ),
1039        ]
1040
1041
1042class UserSourceConnection(SerializerModel, CreatedUpdatedModel):
1043    """Connection between User and Source."""
1044
1045    user = models.ForeignKey(User, on_delete=models.CASCADE)
1046    source = models.ForeignKey(Source, on_delete=models.CASCADE)
1047    identifier = models.TextField()
1048
1049    objects = InheritanceManager()
1050
1051    @property
1052    def serializer(self) -> type[Serializer]:
1053        """Get serializer for this model"""
1054        raise NotImplementedError
1055
1056    def __str__(self) -> str:
1057        return f"User-source connection (user={self.user_id}, source={self.source_id})"
1058
1059    class Meta:
1060        unique_together = (("user", "source"),)
1061        indexes = (
1062            models.Index(fields=("identifier",)),
1063            models.Index(fields=("source", "identifier")),
1064        )
1065
1066
1067class GroupSourceConnection(SerializerModel, CreatedUpdatedModel):
1068    """Connection between Group and Source."""
1069
1070    group = models.ForeignKey(Group, on_delete=models.CASCADE)
1071    source = models.ForeignKey(Source, on_delete=models.CASCADE)
1072    identifier = models.TextField()
1073
1074    objects = InheritanceManager()
1075
1076    @property
1077    def serializer(self) -> type[Serializer]:
1078        """Get serializer for this model"""
1079        raise NotImplementedError
1080
1081    def __str__(self) -> str:
1082        return f"Group-source connection (group={self.group_id}, source={self.source_id})"
1083
1084    class Meta:
1085        unique_together = (("group", "source"),)
1086
1087
1088class ExpiringManager(Manager):
1089    """Manager for expiring objects which filters out expired objects by default"""
1090
1091    def get_queryset(self):
1092        return QuerySet(self.model, using=self._db).exclude(expires__lt=now(), expiring=True)
1093
1094    def including_expired(self):
1095        return QuerySet(self.model, using=self._db)
1096
1097
1098class ExpiringModel(models.Model):
1099    """Base Model which can expire, and is automatically cleaned up."""
1100
1101    expires = models.DateTimeField(default=None, null=True)
1102    expiring = models.BooleanField(default=True)
1103
1104    objects = ExpiringManager()
1105
1106    class Meta:
1107        abstract = True
1108        indexes = [
1109            models.Index(fields=["expires"]),
1110            models.Index(fields=["expiring"]),
1111            models.Index(fields=["expiring", "expires"]),
1112        ]
1113
1114    def expire_action(self, *args, **kwargs):
1115        """Handler which is called when this object is expired. By
1116        default the object is deleted. This is less efficient compared
1117        to bulk deleting objects, but classes like Token() need to change
1118        values instead of being deleted."""
1119        try:
1120            return self.delete(*args, **kwargs)
1121        except self.DoesNotExist:
1122            # Object has already been deleted, so this should be fine
1123            return None
1124
1125    @classmethod
1126    def filter_not_expired(cls, **kwargs) -> QuerySet[Self]:
1127        """Filer for tokens which are not expired yet or are not expiring,
1128        and match filters in `kwargs`"""
1129        from authentik.events.models import Event
1130
1131        deprecation_id = f"{class_to_path(cls)}.filter_not_expired"
1132
1133        Event.log_deprecation(
1134            deprecation_id,
1135            message=(
1136                ".filter_not_expired() is deprecated as the default lookup now excludes "
1137                "expired objects."
1138            ),
1139        )
1140
1141        for obj in (
1142            cls.objects.including_expired()
1143            .filter(**kwargs)
1144            .filter(Q(expires__lt=now(), expiring=True))
1145        ):
1146            obj.delete()
1147        return cls.objects.filter(**kwargs)
1148
1149    @property
1150    def is_expired(self) -> bool:
1151        """Check if token is expired yet."""
1152        if not self.expiring:
1153            return False
1154        return now() > self.expires
1155
1156
1157class TokenIntents(models.TextChoices):
1158    """Intents a Token can be created for."""
1159
1160    # Single use token
1161    INTENT_VERIFICATION = "verification"
1162
1163    # Allow access to API
1164    INTENT_API = "api"
1165
1166    # Recovery use for the recovery app
1167    INTENT_RECOVERY = "recovery"
1168
1169    # App-specific passwords
1170    INTENT_APP_PASSWORD = "app_password"  # nosec
1171
1172
1173class Token(SerializerModel, ManagedModel, ExpiringModel):
1174    """Token used to authenticate the User for API Access or confirm another Stage like Email."""
1175
1176    token_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4)
1177    identifier = models.SlugField(max_length=255, unique=True)
1178    key = models.TextField(default=default_token_key)
1179    intent = models.TextField(
1180        choices=TokenIntents.choices, default=TokenIntents.INTENT_VERIFICATION
1181    )
1182    user = models.ForeignKey("User", on_delete=models.CASCADE, related_name="+")
1183    description = models.TextField(default="", blank=True)
1184
1185    class Meta:
1186        verbose_name = _("Token")
1187        verbose_name_plural = _("Tokens")
1188        indexes = ExpiringModel.Meta.indexes + [
1189            models.Index(fields=["identifier"]),
1190            models.Index(fields=["key"]),
1191        ]
1192        permissions = [
1193            ("view_token_key", _("View token's key")),
1194            ("set_token_key", _("Set a token's key")),
1195        ]
1196
1197    def __str__(self):
1198        description = f"{self.identifier}"
1199        if self.expiring:
1200            description += f" (expires={self.expires})"
1201        return description
1202
1203    @property
1204    def serializer(self) -> type[Serializer]:
1205        from authentik.core.api.tokens import TokenSerializer
1206
1207        return TokenSerializer
1208
1209    def expire_action(self, *args, **kwargs):
1210        """Handler which is called when this object is expired."""
1211        from authentik.events.models import Event, EventAction
1212
1213        if self.intent in [
1214            TokenIntents.INTENT_RECOVERY,
1215            TokenIntents.INTENT_VERIFICATION,
1216            TokenIntents.INTENT_APP_PASSWORD,
1217        ]:
1218            super().expire_action(*args, **kwargs)
1219            return
1220
1221        self.key = default_token_key()
1222        self.expires = default_token_duration()
1223        self.save(*args, **kwargs)
1224        Event.new(
1225            action=EventAction.SECRET_ROTATE,
1226            token=self,
1227            message=f"Token {self.identifier}'s secret was rotated.",
1228        ).save()
1229
1230
1231class PropertyMapping(SerializerModel, ManagedModel):
1232    """User-defined key -> x mapping which can be used by providers to expose extra data."""
1233
1234    pm_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4)
1235    name = models.TextField(unique=True)
1236    expression = models.TextField()
1237
1238    objects = InheritanceManager()
1239
1240    @property
1241    def component(self) -> str:
1242        """Return component used to edit this object"""
1243        raise NotImplementedError
1244
1245    @property
1246    def serializer(self) -> type[Serializer]:
1247        """Get serializer for this model"""
1248        raise NotImplementedError
1249
1250    def evaluate(self, user: User | None, request: HttpRequest | None, **kwargs) -> Any:
1251        """Evaluate `self.expression` using `**kwargs` as Context."""
1252        from authentik.core.expression.evaluator import PropertyMappingEvaluator
1253
1254        evaluator = PropertyMappingEvaluator(self, user, request, **kwargs)
1255        try:
1256            return evaluator.evaluate(self.expression)
1257        except ControlFlowException as exc:
1258            raise exc
1259        except Exception as exc:
1260            raise PropertyMappingExpressionException(exc, self) from exc
1261
1262    def __str__(self):
1263        return f"Property Mapping {self.name}"
1264
1265    class Meta:
1266        verbose_name = _("Property Mapping")
1267        verbose_name_plural = _("Property Mappings")
1268
1269
1270class Session(ExpiringModel, AbstractBaseSession):
1271    """User session with extra fields for fast access"""
1272
1273    # Remove upstream field because we're using our own ExpiringModel
1274    expire_date = None
1275    session_data = models.BinaryField(_("session data"))
1276
1277    # Keep in sync with Session.Keys
1278    last_ip = models.GenericIPAddressField()
1279    last_user_agent = models.TextField(blank=True)
1280    last_used = models.DateTimeField(auto_now=True)
1281
1282    class Meta:
1283        verbose_name = _("Session")
1284        verbose_name_plural = _("Sessions")
1285        indexes = ExpiringModel.Meta.indexes + [
1286            models.Index(fields=["expires", "session_key"]),
1287        ]
1288        default_permissions = []
1289
1290    def __str__(self):
1291        return self.session_key
1292
1293    class Keys(StrEnum):
1294        """
1295        Keys to be set with the session interface for the fields above to be updated.
1296
1297        If a field is added here that needs to be initialized when the session is initialized,
1298        it must also be reflected in authentik.root.middleware.SessionMiddleware.process_request
1299        and in authentik.core.sessions.SessionStore.__init__
1300        """
1301
1302        LAST_IP = "last_ip"
1303        LAST_USER_AGENT = "last_user_agent"
1304        LAST_USED = "last_used"
1305
1306    @classmethod
1307    def get_session_store_class(cls):
1308        from authentik.core.sessions import SessionStore
1309
1310        return SessionStore
1311
1312    def get_decoded(self):
1313        raise NotImplementedError
1314
1315
1316class AuthenticatedSession(SerializerModel):
1317    session = models.OneToOneField(Session, on_delete=models.CASCADE, primary_key=True)
1318    # We use the session as primary key, but we need the API to be able to reference
1319    # this object uniquely without exposing the session key
1320    uuid = models.UUIDField(default=uuid4, unique=True)
1321
1322    user = models.ForeignKey(User, on_delete=models.CASCADE)
1323
1324    @property
1325    def serializer(self) -> type[Serializer]:
1326        from authentik.core.api.authenticated_sessions import AuthenticatedSessionSerializer
1327
1328        return AuthenticatedSessionSerializer
1329
1330    class Meta:
1331        verbose_name = _("Authenticated Session")
1332        verbose_name_plural = _("Authenticated Sessions")
1333
1334    def __str__(self) -> str:
1335        return f"Authenticated Session {str(self.pk)[:10]}"
1336
1337    @staticmethod
1338    def from_request(request: HttpRequest, user: User) -> AuthenticatedSession | None:
1339        """Create a new session from a http request"""
1340        if not hasattr(request, "session") or not request.session.exists(
1341            request.session.session_key
1342        ):
1343            return None
1344        return AuthenticatedSession(
1345            session=Session.objects.filter(session_key=request.session.session_key).first(),
1346            user=user,
1347        )
LOGGER = <BoundLoggerLazyProxy(logger=None, wrapper_class=None, processors=None, context_class=None, initial_values={}, logger_factory_args=())>
USERNAME_MAX_LENGTH = 150
USER_PATH_SYSTEM_PREFIX = 'goauthentik.io'
USER_ATTRIBUTE_DEBUG = 'goauthentik.io/user/debug'
USER_ATTRIBUTE_GENERATED = 'goauthentik.io/user/generated'
USER_ATTRIBUTE_EXPIRES = 'goauthentik.io/user/expires'
USER_ATTRIBUTE_DELETE_ON_LOGOUT = 'goauthentik.io/user/delete-on-logout'
USER_ATTRIBUTE_SOURCES = 'goauthentik.io/user/sources'
USER_ATTRIBUTE_TOKEN_EXPIRING = 'goauthentik.io/user/token-expires'
USER_ATTRIBUTE_TOKEN_MAXIMUM_LIFETIME = 'goauthentik.io/user/token-maximum-lifetime'
USER_ATTRIBUTE_CHANGE_USERNAME = 'goauthentik.io/user/can-change-username'
USER_ATTRIBUTE_CHANGE_NAME = 'goauthentik.io/user/can-change-name'
USER_ATTRIBUTE_CHANGE_EMAIL = 'goauthentik.io/user/can-change-email'
USER_PATH_SERVICE_ACCOUNT = 'goauthentik.io/service-accounts'
GROUP_RECURSION_LIMIT = 20
MANAGED_ROLE_PREFIX_USER = 'ak-managed-role--user'
MANAGED_ROLE_PREFIX_GROUP = 'ak-managed-role--group'
def managed_role_name(user_or_group: django.db.models.base.Model):
84def managed_role_name(user_or_group: models.Model):
85    if isinstance(user_or_group, User):
86        return f"{MANAGED_ROLE_PREFIX_USER}-{user_or_group.pk}"
87    if isinstance(user_or_group, Group):
88        return f"{MANAGED_ROLE_PREFIX_GROUP}-{user_or_group.pk}"
89    raise TypeError("Managed roles are only available for User or Group.")
def default_token_duration() -> datetime.datetime:
 92def default_token_duration() -> datetime:
 93    """Default duration a Token is valid"""
 94    current_tenant = get_current_tenant()
 95    token_duration = (
 96        current_tenant.default_token_duration
 97        if hasattr(current_tenant, "default_token_duration")
 98        else DEFAULT_TOKEN_DURATION
 99    )
100    return now() + timedelta_from_string(token_duration)

Default duration a Token is valid

def default_token_key() -> str:
103def default_token_key() -> str:
104    """Default token key"""
105    current_tenant = get_current_tenant()
106    token_length = (
107        current_tenant.default_token_length
108        if hasattr(current_tenant, "default_token_length")
109        else DEFAULT_TOKEN_LENGTH
110    )
111    # We use generate_id since the chars in the key should be easy
112    # to use in Emails (for verification) and URLs (for recovery)
113    return generate_id(token_length)

Default token key

class UserTypes(django.db.models.enums.TextChoices):
116class UserTypes(models.TextChoices):
117    """User types, both for grouping, licensing and permissions in the case
118    of the internal_service_account"""
119
120    INTERNAL = "internal"
121    EXTERNAL = "external"
122
123    # User-created service accounts
124    SERVICE_ACCOUNT = "service_account"
125
126    # Special user type for internally managed and created service
127    # accounts, such as outpost users
128    INTERNAL_SERVICE_ACCOUNT = "internal_service_account"

User types, both for grouping, licensing and permissions in the case of the internal_service_account

INTERNAL = UserTypes.INTERNAL
EXTERNAL = UserTypes.EXTERNAL
SERVICE_ACCOUNT = UserTypes.SERVICE_ACCOUNT
INTERNAL_SERVICE_ACCOUNT = UserTypes.INTERNAL_SERVICE_ACCOUNT
class AttributesMixin(django.db.models.base.Model):
131class AttributesMixin(models.Model):
132    """Adds an attributes property to a model"""
133
134    attributes = models.JSONField(default=dict, blank=True)
135
136    class Meta:
137        abstract = True
138
139    def update_attributes(self, properties: dict[str, Any]):
140        """Update fields and attributes, but correctly by merging dicts"""
141        needs_update = False
142        for key, value in properties.items():
143            if key == "attributes":
144                continue
145            if getattr(self, key, None) != value:
146                setattr(self, key, value)
147                needs_update = True
148        final_attributes = {}
149        MERGE_LIST_UNIQUE.merge(final_attributes, self.attributes)
150        MERGE_LIST_UNIQUE.merge(final_attributes, properties.get("attributes", {}))
151        if self.attributes != final_attributes:
152            self.attributes = final_attributes
153            needs_update = True
154        if needs_update:
155            self.save()
156
157    @classmethod
158    def update_or_create_attributes(
159        cls, query: dict[str, Any], properties: dict[str, Any]
160    ) -> tuple[Self, bool]:
161        """Same as django's update_or_create but correctly updates attributes by merging dicts"""
162        instance = cls.objects.filter(**query).first()
163        if not instance:
164            return cls.objects.create(**properties), True
165        instance.update_attributes(properties)
166        return instance, False

Adds an attributes property to a model

def attributes(unknown):

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

def update_attributes(self, properties: dict[str, typing.Any]):
139    def update_attributes(self, properties: dict[str, Any]):
140        """Update fields and attributes, but correctly by merging dicts"""
141        needs_update = False
142        for key, value in properties.items():
143            if key == "attributes":
144                continue
145            if getattr(self, key, None) != value:
146                setattr(self, key, value)
147                needs_update = True
148        final_attributes = {}
149        MERGE_LIST_UNIQUE.merge(final_attributes, self.attributes)
150        MERGE_LIST_UNIQUE.merge(final_attributes, properties.get("attributes", {}))
151        if self.attributes != final_attributes:
152            self.attributes = final_attributes
153            needs_update = True
154        if needs_update:
155            self.save()

Update fields and attributes, but correctly by merging dicts

@classmethod
def update_or_create_attributes( cls, query: dict[str, typing.Any], properties: dict[str, typing.Any]) -> tuple[typing.Self, bool]:
157    @classmethod
158    def update_or_create_attributes(
159        cls, query: dict[str, Any], properties: dict[str, Any]
160    ) -> tuple[Self, bool]:
161        """Same as django's update_or_create but correctly updates attributes by merging dicts"""
162        instance = cls.objects.filter(**query).first()
163        if not instance:
164            return cls.objects.create(**properties), True
165        instance.update_attributes(properties)
166        return instance, False

Same as django's update_or_create but correctly updates attributes by merging dicts

class AttributesMixin.Meta:
136    class Meta:
137        abstract = True
abstract = False
class GroupQuerySet(django.db.models.query.QuerySet):
169class GroupQuerySet(QuerySet):
170    def with_descendants(self):
171        pks = self.values_list("pk", flat=True)
172        return Group.objects.filter(Q(pk__in=pks) | Q(ancestor_nodes__ancestor__in=pks)).distinct()
173
174    def with_ancestors(self):
175        pks = self.values_list("pk", flat=True)
176        return Group.objects.filter(
177            Q(pk__in=pks) | Q(descendant_nodes__descendant__in=pks)
178        ).distinct()

Represent a lazy database lookup for a set of objects.

def with_descendants(self):
170    def with_descendants(self):
171        pks = self.values_list("pk", flat=True)
172        return Group.objects.filter(Q(pk__in=pks) | Q(ancestor_nodes__ancestor__in=pks)).distinct()
def with_ancestors(self):
174    def with_ancestors(self):
175        pks = self.values_list("pk", flat=True)
176        return Group.objects.filter(
177            Q(pk__in=pks) | Q(descendant_nodes__descendant__in=pks)
178        ).distinct()
181class Group(SerializerModel, AttributesMixin):
182    """Group model which supports a hierarchy and has attributes"""
183
184    group_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4)
185
186    name = models.TextField(verbose_name=_("name"), unique=True)
187    is_superuser = models.BooleanField(
188        default=False, help_text=_("Users added to this group will be superusers.")
189    )
190
191    roles = models.ManyToManyField("authentik_rbac.Role", related_name="groups", blank=True)
192
193    parents = models.ManyToManyField(
194        "Group",
195        blank=True,
196        symmetrical=False,
197        through="GroupParentageNode",
198        related_name="children",
199    )
200
201    objects = GroupQuerySet.as_manager()
202
203    class Meta:
204        indexes = (
205            models.Index(fields=["name"]),
206            models.Index(fields=["is_superuser"]),
207        )
208        verbose_name = _("Group")
209        verbose_name_plural = _("Groups")
210        permissions = [
211            ("add_user_to_group", _("Add user to group")),
212            ("remove_user_from_group", _("Remove user from group")),
213            ("enable_group_superuser", _("Enable superuser status")),
214            ("disable_group_superuser", _("Disable superuser status")),
215        ]
216
217    def __str__(self):
218        return f"Group {self.name}"
219
220    @property
221    def serializer(self) -> Serializer:
222        from authentik.core.api.groups import GroupSerializer
223
224        return GroupSerializer
225
226    @property
227    def num_pk(self) -> int:
228        """Get a numerical, int32 ID for the group"""
229        # int max is 2147483647 (10 digits) so 9 is the max usable
230        # in the LDAP Outpost we use the last 5 chars so match here
231        return int(str(self.pk.int)[:5])
232
233    def is_member(self, user: User) -> bool:
234        """Recursively check if `user` is member of us, or any parent."""
235        return user.all_groups().filter(group_uuid=self.group_uuid).exists()
236
237    def all_roles(self) -> QuerySet[Role]:
238        """Get all roles of this group and all of its ancestors."""
239        return Role.objects.filter(
240            groups__in=Group.objects.filter(pk=self.pk).with_ancestors()
241        ).distinct()
242
243    def get_managed_role(self, create=False):
244        if create:
245            name = managed_role_name(self)
246            role, created = Role.objects.get_or_create(name=name, managed=name)
247            if created:
248                role.groups.add(self)
249            return role
250        else:
251            return Role.objects.filter(name=managed_role_name(self)).first()
252
253    def assign_perms_to_managed_role(
254        self,
255        perms: str | list[str] | Permission | list[Permission],
256        obj: models.Model | None = None,
257    ):
258        if not perms:
259            return
260        role = self.get_managed_role(create=True)
261        role.assign_perms(perms, obj)

Group model which supports a hierarchy and has attributes

def group_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 is_superuser(unknown):

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

roles

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.

parents

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

The type of the None singleton.

serializer: rest_framework.serializers.Serializer
220    @property
221    def serializer(self) -> Serializer:
222        from authentik.core.api.groups import GroupSerializer
223
224        return GroupSerializer

Get serializer for this model

num_pk: int
226    @property
227    def num_pk(self) -> int:
228        """Get a numerical, int32 ID for the group"""
229        # int max is 2147483647 (10 digits) so 9 is the max usable
230        # in the LDAP Outpost we use the last 5 chars so match here
231        return int(str(self.pk.int)[:5])

Get a numerical, int32 ID for the group

def is_member(self, user: User) -> bool:
233    def is_member(self, user: User) -> bool:
234        """Recursively check if `user` is member of us, or any parent."""
235        return user.all_groups().filter(group_uuid=self.group_uuid).exists()

Recursively check if user is member of us, or any parent.

def all_roles(self) -> django.db.models.query.QuerySet:
237    def all_roles(self) -> QuerySet[Role]:
238        """Get all roles of this group and all of its ancestors."""
239        return Role.objects.filter(
240            groups__in=Group.objects.filter(pk=self.pk).with_ancestors()
241        ).distinct()

Get all roles of this group and all of its ancestors.

def get_managed_role(self, create=False):
243    def get_managed_role(self, create=False):
244        if create:
245            name = managed_role_name(self)
246            role, created = Role.objects.get_or_create(name=name, managed=name)
247            if created:
248                role.groups.add(self)
249            return role
250        else:
251            return Role.objects.filter(name=managed_role_name(self)).first()
def assign_perms_to_managed_role( self, perms: str | list[str] | django.contrib.auth.models.Permission | list[django.contrib.auth.models.Permission], obj: django.db.models.base.Model | None = None):
253    def assign_perms_to_managed_role(
254        self,
255        perms: str | list[str] | Permission | list[Permission],
256        obj: models.Model | None = None,
257    ):
258        if not perms:
259            return
260        role = self.get_managed_role(create=True)
261        role.assign_perms(perms, obj)
def attributes(unknown):

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

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

children

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.

parent_nodes

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.

child_nodes

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.

ancestor_nodes

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.

descendant_nodes

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.

users

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

The requested object does not exist

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

The query returned multiple objects when only one was expected.

class GroupParentageNode(django.db.models.base.Model):
264class GroupParentageNode(models.Model):
265    uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4)
266
267    child = models.ForeignKey(Group, related_name="parent_nodes", on_delete=models.CASCADE)
268    parent = models.ForeignKey(Group, related_name="child_nodes", on_delete=models.CASCADE)
269
270    class Meta:
271        verbose_name = _("Group Parentage Node")
272        verbose_name_plural = _("Group Parentage Nodes")
273
274        db_table = "authentik_core_groupparentage"
275
276        triggers = [
277            pgtrigger.Trigger(
278                name="refresh_groupancestry",
279                operation=pgtrigger.Insert | pgtrigger.Update | pgtrigger.Delete,
280                when=pgtrigger.After,
281                func="""
282                    REFRESH MATERIALIZED VIEW CONCURRENTLY authentik_core_groupancestry;
283                    RETURN NULL;
284                """,
285            ),
286        ]
287
288    def __str__(self) -> str:
289        return f"Group Parentage Node from #{self.child_id} to {self.parent_id}"

GroupParentageNode(uuid, child, parent)

def uuid(unknown):

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

child

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.

parent

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.

child_id
parent_id
def objects(unknown):

The type of the None singleton.

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

The requested object does not exist

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

The query returned multiple objects when only one was expected.

class GroupAncestryNode(psqlextra.models.view.PostgresMaterializedViewModel):
292class GroupAncestryNode(PostgresMaterializedViewModel):
293    descendant = models.ForeignKey(
294        Group, related_name="ancestor_nodes", on_delete=models.DO_NOTHING
295    )
296    ancestor = models.ForeignKey(
297        Group, related_name="descendant_nodes", on_delete=models.DO_NOTHING
298    )
299
300    class Meta:
301        # This is a transitive closure of authentik_core_groupparentage
302        # See https://en.wikipedia.org/wiki/Transitive_closure#In_graph_theory
303        db_table = "authentik_core_groupancestry"
304        indexes = [
305            models.Index(fields=["descendant"]),
306            models.Index(fields=["ancestor"]),
307            UniqueIndex(fields=["id"]),
308        ]
309
310    class ViewMeta:
311        query = """
312            WITH RECURSIVE accumulator AS (
313                SELECT
314                child_id::text || '-' || parent_id::text as id,
315                child_id AS descendant_id,
316                parent_id AS ancestor_id
317                FROM authentik_core_groupparentage
318
319                UNION
320
321                SELECT
322                accumulator.descendant_id::text || '-' || current.parent_id::text as id,
323                accumulator.descendant_id,
324                current.parent_id AS ancestor_id
325                FROM accumulator
326                JOIN authentik_core_groupparentage current
327                ON accumulator.ancestor_id = current.child_id
328            )
329            SELECT * FROM accumulator
330        """
331
332    def __str__(self) -> str:
333        return f"Group Ancestry Node from {self.descendant_id} to {self.ancestor_id}"

GroupAncestryNode(id, descendant, ancestor)

descendant

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.

ancestor

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.

descendant_id
ancestor_id
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 GroupAncestryNode.ViewMeta:
310    class ViewMeta:
311        query = """
312            WITH RECURSIVE accumulator AS (
313                SELECT
314                child_id::text || '-' || parent_id::text as id,
315                child_id AS descendant_id,
316                parent_id AS ancestor_id
317                FROM authentik_core_groupparentage
318
319                UNION
320
321                SELECT
322                accumulator.descendant_id::text || '-' || current.parent_id::text as id,
323                accumulator.descendant_id,
324                current.parent_id AS ancestor_id
325                FROM accumulator
326                JOIN authentik_core_groupparentage current
327                ON accumulator.ancestor_id = current.child_id
328            )
329            SELECT * FROM accumulator
330        """
query = "\n WITH RECURSIVE accumulator AS (\n SELECT\n child_id::text || '-' || parent_id::text as id,\n child_id AS descendant_id,\n parent_id AS ancestor_id\n FROM authentik_core_groupparentage\n\n UNION\n\n SELECT\n accumulator.descendant_id::text || '-' || current.parent_id::text as id,\n accumulator.descendant_id,\n current.parent_id AS ancestor_id\n FROM accumulator\n JOIN authentik_core_groupparentage current\n ON accumulator.ancestor_id = current.child_id\n )\n SELECT * FROM accumulator\n "
class GroupAncestryNode.DoesNotExist(django.core.exceptions.ObjectDoesNotExist):

The requested object does not exist

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

The query returned multiple objects when only one was expected.

class UserQuerySet(django.db.models.query.QuerySet):
336class UserQuerySet(models.QuerySet):
337    """User queryset"""
338
339    def exclude_anonymous(self):
340        """Exclude anonymous user"""
341        return self.exclude(**{User.USERNAME_FIELD: settings.ANONYMOUS_USER_NAME})

User queryset

def exclude_anonymous(self):
339    def exclude_anonymous(self):
340        """Exclude anonymous user"""
341        return self.exclude(**{User.USERNAME_FIELD: settings.ANONYMOUS_USER_NAME})

Exclude anonymous user

class UserManager(django.contrib.auth.models.UserManager):
344class UserManager(DjangoUserManager):
345    """User manager that doesn't assign is_superuser and is_staff"""
346
347    def get_queryset(self):
348        """Create special user queryset"""
349        return UserQuerySet(self.model, using=self._db)
350
351    def create_user(self, username, email=None, password=None, **extra_fields):
352        """User manager that doesn't assign is_superuser and is_staff"""
353        return self._create_user(username, email, password, **extra_fields)
354
355    def exclude_anonymous(self) -> QuerySet:
356        """Exclude anonymous user"""
357        return self.get_queryset().exclude_anonymous()

User manager that doesn't assign is_superuser and is_staff

def get_queryset(self):
347    def get_queryset(self):
348        """Create special user queryset"""
349        return UserQuerySet(self.model, using=self._db)

Create special user queryset

def create_user(self, username, email=None, password=None, **extra_fields):
351    def create_user(self, username, email=None, password=None, **extra_fields):
352        """User manager that doesn't assign is_superuser and is_staff"""
353        return self._create_user(username, email, password, **extra_fields)

User manager that doesn't assign is_superuser and is_staff

def exclude_anonymous(self) -> django.db.models.query.QuerySet:
355    def exclude_anonymous(self) -> QuerySet:
356        """Exclude anonymous user"""
357        return self.get_queryset().exclude_anonymous()

Exclude anonymous user

class User(authentik.lib.models.SerializerModel, AttributesMixin, django.contrib.auth.models.AbstractUser):
360class User(SerializerModel, AttributesMixin, AbstractUser):
361    """authentik User model, based on django's contrib auth user model."""
362
363    # Overwriting PermissionsMixin: permissions are handled by roles.
364    # (This knowingly violates the Liskov substitution principle. It is better to fail loudly.)
365    user_permissions = None
366
367    uuid = models.UUIDField(default=uuid4, editable=False, unique=True)
368    name = models.TextField(help_text=_("User's display name."))
369    path = models.TextField(default="users")
370    type = models.TextField(choices=UserTypes.choices, default=UserTypes.INTERNAL)
371
372    sources = models.ManyToManyField("Source", through="UserSourceConnection")
373    groups = models.ManyToManyField("Group", related_name="users")
374    roles = models.ManyToManyField("authentik_rbac.Role", related_name="users", blank=True)
375    password_change_date = models.DateTimeField(auto_now_add=True)
376
377    last_updated = models.DateTimeField(auto_now=True)
378
379    objects = UserManager()
380
381    class Meta:
382        verbose_name = _("User")
383        verbose_name_plural = _("Users")
384        permissions = [
385            ("reset_user_password", _("Reset Password")),
386            ("impersonate", _("Can impersonate other users")),
387            ("preview_user", _("Can preview user data sent to providers")),
388            ("view_user_applications", _("View applications the user has access to")),
389        ]
390        indexes = [
391            models.Index(fields=["last_login"]),
392            models.Index(fields=["password_change_date"]),
393            models.Index(fields=["uuid"]),
394            models.Index(fields=["path"]),
395            models.Index(fields=["type"]),
396            models.Index(fields=["date_joined"]),
397            models.Index(fields=["last_updated"]),
398        ]
399
400    def __str__(self):
401        return self.username
402
403    @staticmethod
404    def default_path() -> str:
405        """Get the default user path"""
406        return User._meta.get_field("path").default
407
408    def all_groups(self) -> QuerySet[Group]:
409        """Recursively get all groups this user is a member of."""
410        return self.groups.all().with_ancestors()
411
412    def all_roles(self) -> QuerySet[Role]:
413        """Get all roles of this user and all of its groups (recursively)."""
414        return Role.objects.filter(Q(users=self) | Q(groups__in=self.all_groups())).distinct()
415
416    def get_managed_role(self, create=False):
417        if create:
418            name = managed_role_name(self)
419            role, created = Role.objects.get_or_create(name=name, managed=name)
420            if created:
421                role.users.add(self)
422            return role
423        else:
424            return Role.objects.filter(name=managed_role_name(self)).first()
425
426    def get_all_model_perms_on_managed_role(self) -> QuerySet[RoleModelPermission]:
427        role = self.get_managed_role()
428        if not role:
429            return RoleModelPermission.objects.none()
430        return RoleModelPermission.objects.filter(role=role)
431
432    def get_all_obj_perms_on_managed_role(self) -> QuerySet[RoleObjectPermission]:
433        role = self.get_managed_role()
434        if not role:
435            return RoleObjectPermission.objects.none()
436        return RoleObjectPermission.objects.filter(role=role)
437
438    def assign_perms_to_managed_role(
439        self,
440        perms: str | list[str] | Permission | list[Permission],
441        obj: models.Model | None = None,
442    ):
443        if not perms:
444            return
445        role = self.get_managed_role(create=True)
446        role.assign_perms(perms, obj)
447
448    def remove_perms_from_managed_role(
449        self,
450        perms: str | list[str] | Permission | list[Permission],
451        obj: models.Model | None = None,
452    ):
453        role = self.get_managed_role()
454        if not role:
455            return None
456        role.remove_perms(perms, obj)
457
458    def remove_all_perms_from_managed_role(self):
459        role = self.get_managed_role()
460        if not role:
461            return None
462        RoleModelPermission.objects.filter(role=role).delete()
463        RoleObjectPermission.objects.filter(role=role).delete()
464
465    def group_attributes(self, request: HttpRequest | None = None) -> dict[str, Any]:
466        """Get a dictionary containing the attributes from all groups the user belongs to,
467        including the users attributes"""
468        final_attributes = {}
469        if request and hasattr(request, "brand"):
470            always_merger.merge(final_attributes, request.brand.attributes)
471        for group in self.all_groups().order_by("name"):
472            always_merger.merge(final_attributes, group.attributes)
473        always_merger.merge(final_attributes, self.attributes)
474        return final_attributes
475
476    def app_entitlements(self, app: Application | None) -> QuerySet[ApplicationEntitlement]:
477        """Get all entitlements this user has for `app`."""
478        if not app:
479            return []
480        all_groups = self.all_groups()
481        qs = app.applicationentitlement_set.filter(
482            Q(
483                Q(bindings__user=self) | Q(bindings__group__in=all_groups),
484                bindings__negate=False,
485            )
486            | Q(
487                Q(~Q(bindings__user=self), bindings__user__isnull=False)
488                | Q(~Q(bindings__group__in=all_groups), bindings__group__isnull=False),
489                bindings__negate=True,
490            ),
491            bindings__enabled=True,
492        ).order_by("name")
493        return qs
494
495    def app_entitlements_attributes(self, app: Application | None) -> dict:
496        """Get a dictionary containing all merged attributes from app entitlements for `app`."""
497        final_attributes = {}
498        for attrs in self.app_entitlements(app).values_list("attributes", flat=True):
499            always_merger.merge(final_attributes, attrs)
500        return final_attributes
501
502    @property
503    def serializer(self) -> Serializer:
504        from authentik.core.api.users import UserSerializer
505
506        return UserSerializer
507
508    @cached_property
509    def is_superuser(self) -> bool:
510        """Get supseruser status based on membership in a group with superuser status"""
511        return self.all_groups().filter(is_superuser=True).exists()
512
513    @property
514    def is_staff(self) -> bool:
515        """superuser == staff user"""
516        return self.is_superuser  # type: ignore
517
518    # TODO: remove this after 2026.
519    @property
520    def ak_groups(self):
521        """This is a proxy for a renamed, deprecated field."""
522        from authentik.events.models import Event
523
524        deprecation = "authentik.core.models.User.ak_groups"
525        replacement = "authentik.core.models.User.groups"
526        message_logger = (
527            f"{deprecation} is deprecated and will be removed in a future version of "
528            f"authentik. Please use {replacement} instead."
529        )
530        message_event = (
531            f"{message_logger} This event will not be repeated until it expires (by "
532            "default: in 30 days). See authentik logs for every will invocation of this "
533            "deprecation."
534        )
535        stacktrace = traceback.format_stack()
536        # The last line is this function, the next-to-last line is its caller
537        cause = stacktrace[-2] if len(stacktrace) > 1 else "Unknown, see stacktrace in logs"
538        if search := re.search(r'"(.*?)"', cause):
539            cause = f"Property mapping or Expression policy named {search.group(1)}"
540
541        LOGGER.warning(
542            "deprecation used",
543            message=message_logger,
544            deprecation=deprecation,
545            replacement=replacement,
546            cause=cause,
547            stacktrace=stacktrace,
548        )
549        Event.log_deprecation(
550            deprecation, message=message_event, cause=cause, replacement=replacement
551        )
552        return self.groups
553
554    def set_password(self, raw_password, signal=True, sender=None, request=None):
555        if self.pk and signal:
556            from authentik.core.signals import password_changed
557
558            if not sender:
559                sender = self
560            password_changed.send(sender=sender, user=self, password=raw_password, request=request)
561        self.password_change_date = now()
562        return super().set_password(raw_password)
563
564    def check_password(self, raw_password: str) -> bool:
565        """
566        Return a boolean of whether the raw_password was correct. Handles
567        hashing formats behind the scenes.
568
569        Slightly changed version which doesn't send a signal for such internal hash upgrades
570        """
571
572        def setter(raw_password):
573            self.set_password(raw_password, signal=False)
574            # Password hash upgrades shouldn't be considered password changes.
575            self._password = None
576            self.save(update_fields=["password"])
577
578        return check_password(raw_password, self.password, setter)
579
580    @property
581    def uid(self) -> str:
582        """Generate a globally unique UID, based on the user ID and the hashed secret key"""
583        return sha256(f"{self.id}-{get_unique_identifier()}".encode("ascii")).hexdigest()
584
585    def locale(self, request: HttpRequest | None = None) -> str:
586        """Get the locale the user has configured"""
587        if request and hasattr(request, "LANGUAGE_CODE"):
588            return request.LANGUAGE_CODE
589        try:
590            return self.attributes.get("settings", {}).get("locale", "")
591
592        except Exception as exc:  # noqa
593            LOGGER.warning("Failed to get default locale", exc=exc)
594        if request:
595            return request.brand.locale
596        return ""
597
598    @property
599    def avatar(self) -> str:
600        """Get avatar, depending on authentik.avatar setting"""
601        return get_avatar(self)

authentik User model, based on django's contrib auth user model.

user_permissions = None
def 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 path(unknown):

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

def type(unknown):

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

sources

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.

groups

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.

roles

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 password_change_date(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.

def objects(unknown):

The type of the None singleton.

@staticmethod
def default_path() -> str:
403    @staticmethod
404    def default_path() -> str:
405        """Get the default user path"""
406        return User._meta.get_field("path").default

Get the default user path

def all_groups(self) -> django.db.models.query.QuerySet:
408    def all_groups(self) -> QuerySet[Group]:
409        """Recursively get all groups this user is a member of."""
410        return self.groups.all().with_ancestors()

Recursively get all groups this user is a member of.

def all_roles(self) -> django.db.models.query.QuerySet:
412    def all_roles(self) -> QuerySet[Role]:
413        """Get all roles of this user and all of its groups (recursively)."""
414        return Role.objects.filter(Q(users=self) | Q(groups__in=self.all_groups())).distinct()

Get all roles of this user and all of its groups (recursively).

def get_managed_role(self, create=False):
416    def get_managed_role(self, create=False):
417        if create:
418            name = managed_role_name(self)
419            role, created = Role.objects.get_or_create(name=name, managed=name)
420            if created:
421                role.users.add(self)
422            return role
423        else:
424            return Role.objects.filter(name=managed_role_name(self)).first()
def get_all_model_perms_on_managed_role(self) -> django.db.models.query.QuerySet:
426    def get_all_model_perms_on_managed_role(self) -> QuerySet[RoleModelPermission]:
427        role = self.get_managed_role()
428        if not role:
429            return RoleModelPermission.objects.none()
430        return RoleModelPermission.objects.filter(role=role)
def get_all_obj_perms_on_managed_role(self) -> django.db.models.query.QuerySet:
432    def get_all_obj_perms_on_managed_role(self) -> QuerySet[RoleObjectPermission]:
433        role = self.get_managed_role()
434        if not role:
435            return RoleObjectPermission.objects.none()
436        return RoleObjectPermission.objects.filter(role=role)
def assign_perms_to_managed_role( self, perms: str | list[str] | django.contrib.auth.models.Permission | list[django.contrib.auth.models.Permission], obj: django.db.models.base.Model | None = None):
438    def assign_perms_to_managed_role(
439        self,
440        perms: str | list[str] | Permission | list[Permission],
441        obj: models.Model | None = None,
442    ):
443        if not perms:
444            return
445        role = self.get_managed_role(create=True)
446        role.assign_perms(perms, obj)
def remove_perms_from_managed_role( self, perms: str | list[str] | django.contrib.auth.models.Permission | list[django.contrib.auth.models.Permission], obj: django.db.models.base.Model | None = None):
448    def remove_perms_from_managed_role(
449        self,
450        perms: str | list[str] | Permission | list[Permission],
451        obj: models.Model | None = None,
452    ):
453        role = self.get_managed_role()
454        if not role:
455            return None
456        role.remove_perms(perms, obj)
def remove_all_perms_from_managed_role(self):
458    def remove_all_perms_from_managed_role(self):
459        role = self.get_managed_role()
460        if not role:
461            return None
462        RoleModelPermission.objects.filter(role=role).delete()
463        RoleObjectPermission.objects.filter(role=role).delete()
def group_attributes( self, request: django.http.request.HttpRequest | None = None) -> dict[str, typing.Any]:
465    def group_attributes(self, request: HttpRequest | None = None) -> dict[str, Any]:
466        """Get a dictionary containing the attributes from all groups the user belongs to,
467        including the users attributes"""
468        final_attributes = {}
469        if request and hasattr(request, "brand"):
470            always_merger.merge(final_attributes, request.brand.attributes)
471        for group in self.all_groups().order_by("name"):
472            always_merger.merge(final_attributes, group.attributes)
473        always_merger.merge(final_attributes, self.attributes)
474        return final_attributes

Get a dictionary containing the attributes from all groups the user belongs to, including the users attributes

def app_entitlements( self, app: Application | None) -> django.db.models.query.QuerySet:
476    def app_entitlements(self, app: Application | None) -> QuerySet[ApplicationEntitlement]:
477        """Get all entitlements this user has for `app`."""
478        if not app:
479            return []
480        all_groups = self.all_groups()
481        qs = app.applicationentitlement_set.filter(
482            Q(
483                Q(bindings__user=self) | Q(bindings__group__in=all_groups),
484                bindings__negate=False,
485            )
486            | Q(
487                Q(~Q(bindings__user=self), bindings__user__isnull=False)
488                | Q(~Q(bindings__group__in=all_groups), bindings__group__isnull=False),
489                bindings__negate=True,
490            ),
491            bindings__enabled=True,
492        ).order_by("name")
493        return qs

Get all entitlements this user has for app.

def app_entitlements_attributes(self, app: Application | None) -> dict:
495    def app_entitlements_attributes(self, app: Application | None) -> dict:
496        """Get a dictionary containing all merged attributes from app entitlements for `app`."""
497        final_attributes = {}
498        for attrs in self.app_entitlements(app).values_list("attributes", flat=True):
499            always_merger.merge(final_attributes, attrs)
500        return final_attributes

Get a dictionary containing all merged attributes from app entitlements for app.

serializer: rest_framework.serializers.Serializer
502    @property
503    def serializer(self) -> Serializer:
504        from authentik.core.api.users import UserSerializer
505
506        return UserSerializer

Get serializer for this model

def is_superuser(unknown):

Get supseruser status based on membership in a group with superuser status

is_staff: bool
513    @property
514    def is_staff(self) -> bool:
515        """superuser == staff user"""
516        return self.is_superuser  # type: ignore

superuser == staff user

ak_groups
519    @property
520    def ak_groups(self):
521        """This is a proxy for a renamed, deprecated field."""
522        from authentik.events.models import Event
523
524        deprecation = "authentik.core.models.User.ak_groups"
525        replacement = "authentik.core.models.User.groups"
526        message_logger = (
527            f"{deprecation} is deprecated and will be removed in a future version of "
528            f"authentik. Please use {replacement} instead."
529        )
530        message_event = (
531            f"{message_logger} This event will not be repeated until it expires (by "
532            "default: in 30 days). See authentik logs for every will invocation of this "
533            "deprecation."
534        )
535        stacktrace = traceback.format_stack()
536        # The last line is this function, the next-to-last line is its caller
537        cause = stacktrace[-2] if len(stacktrace) > 1 else "Unknown, see stacktrace in logs"
538        if search := re.search(r'"(.*?)"', cause):
539            cause = f"Property mapping or Expression policy named {search.group(1)}"
540
541        LOGGER.warning(
542            "deprecation used",
543            message=message_logger,
544            deprecation=deprecation,
545            replacement=replacement,
546            cause=cause,
547            stacktrace=stacktrace,
548        )
549        Event.log_deprecation(
550            deprecation, message=message_event, cause=cause, replacement=replacement
551        )
552        return self.groups

This is a proxy for a renamed, deprecated field.

def set_password(self, raw_password, signal=True, sender=None, request=None):
554    def set_password(self, raw_password, signal=True, sender=None, request=None):
555        if self.pk and signal:
556            from authentik.core.signals import password_changed
557
558            if not sender:
559                sender = self
560            password_changed.send(sender=sender, user=self, password=raw_password, request=request)
561        self.password_change_date = now()
562        return super().set_password(raw_password)
def check_password(self, raw_password: str) -> bool:
564    def check_password(self, raw_password: str) -> bool:
565        """
566        Return a boolean of whether the raw_password was correct. Handles
567        hashing formats behind the scenes.
568
569        Slightly changed version which doesn't send a signal for such internal hash upgrades
570        """
571
572        def setter(raw_password):
573            self.set_password(raw_password, signal=False)
574            # Password hash upgrades shouldn't be considered password changes.
575            self._password = None
576            self.save(update_fields=["password"])
577
578        return check_password(raw_password, self.password, setter)

Return a boolean of whether the raw_password was correct. Handles hashing formats behind the scenes.

Slightly changed version which doesn't send a signal for such internal hash upgrades

uid: str
580    @property
581    def uid(self) -> str:
582        """Generate a globally unique UID, based on the user ID and the hashed secret key"""
583        return sha256(f"{self.id}-{get_unique_identifier()}".encode("ascii")).hexdigest()

Generate a globally unique UID, based on the user ID and the hashed secret key

def locale(self, request: django.http.request.HttpRequest | None = None) -> str:
585    def locale(self, request: HttpRequest | None = None) -> str:
586        """Get the locale the user has configured"""
587        if request and hasattr(request, "LANGUAGE_CODE"):
588            return request.LANGUAGE_CODE
589        try:
590            return self.attributes.get("settings", {}).get("locale", "")
591
592        except Exception as exc:  # noqa
593            LOGGER.warning("Failed to get default locale", exc=exc)
594        if request:
595            return request.brand.locale
596        return ""

Get the locale the user has configured

avatar: str
598    @property
599    def avatar(self) -> str:
600        """Get avatar, depending on authentik.avatar setting"""
601        return get_avatar(self)

Get avatar, depending on authentik.avatar setting

def attributes(unknown):

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

def username(unknown):

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

def first_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 last_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 email(unknown):

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

def is_active(unknown):

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

def date_joined(unknown):

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

def password(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_login(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_type_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_next_by_password_change_date(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_password_change_date(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 get_next_by_date_joined(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_date_joined(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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

old_passwords

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.

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

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

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

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

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

The requested object does not exist

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

The query returned multiple objects when only one was expected.

class Provider(authentik.lib.models.SerializerModel):
604class Provider(SerializerModel):
605    """Application-independent Provider instance. For example SAML2 Remote, OAuth2 Application"""
606
607    name = models.TextField(unique=True)
608
609    authentication_flow = models.ForeignKey(
610        "authentik_flows.Flow",
611        null=True,
612        on_delete=models.SET_NULL,
613        help_text=_(
614            "Flow used for authentication when the associated application is accessed by an "
615            "un-authenticated user."
616        ),
617        related_name="provider_authentication",
618    )
619    authorization_flow = models.ForeignKey(
620        "authentik_flows.Flow",
621        # Set to cascade even though null is allowed, since most providers
622        # still require an authorization flow set
623        on_delete=models.CASCADE,
624        null=True,
625        help_text=_("Flow used when authorizing this provider."),
626        related_name="provider_authorization",
627    )
628    invalidation_flow = models.ForeignKey(
629        "authentik_flows.Flow",
630        on_delete=models.SET_DEFAULT,
631        default=None,
632        null=True,
633        help_text=_("Flow used ending the session from a provider."),
634        related_name="provider_invalidation",
635    )
636
637    property_mappings = models.ManyToManyField("PropertyMapping", default=None, blank=True)
638
639    backchannel_application = models.ForeignKey(
640        "Application",
641        default=None,
642        null=True,
643        on_delete=models.CASCADE,
644        help_text=_(
645            "Accessed from applications; optional backchannel providers for protocols "
646            "like LDAP and SCIM."
647        ),
648        related_name="backchannel_providers",
649    )
650
651    is_backchannel = models.BooleanField(default=False)
652
653    objects = InheritanceManager()
654
655    @property
656    def launch_url(self) -> str | None:
657        """URL to this provider and initiate authorization for the user.
658        Can return None for providers that are not URL-based"""
659        return None
660
661    @property
662    def icon_url(self) -> str | None:
663        return None
664
665    @property
666    def component(self) -> str:
667        """Return component used to edit this object"""
668        raise NotImplementedError
669
670    @property
671    def serializer(self) -> type[Serializer]:
672        """Get serializer for this model"""
673        raise NotImplementedError
674
675    def __str__(self):
676        return str(self.name)

Application-independent Provider instance. For example SAML2 Remote, OAuth2 Application

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.

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

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

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

property_mappings

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.

backchannel_application

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 is_backchannel(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.

launch_url: str | None
655    @property
656    def launch_url(self) -> str | None:
657        """URL to this provider and initiate authorization for the user.
658        Can return None for providers that are not URL-based"""
659        return None

URL to this provider and initiate authorization for the user. Can return None for providers that are not URL-based

icon_url: str | None
661    @property
662    def icon_url(self) -> str | None:
663        return None
component: str
665    @property
666    def component(self) -> str:
667        """Return component used to edit this object"""
668        raise NotImplementedError

Return component used to edit this object

serializer: type[rest_framework.serializers.Serializer]
670    @property
671    def serializer(self) -> type[Serializer]:
672        """Get serializer for this model"""
673        raise NotImplementedError

Get serializer for this model

authentication_flow_id
authorization_flow_id
invalidation_flow_id
backchannel_application_id
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.

application

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.

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

oauth2provider

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.

ldapprovider

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.

racprovider

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.

radiusprovider

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.

samlprovider

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.

scimprovider

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.

googleworkspaceprovider

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.

microsoftentraprovider

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.

ssfprovider

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 Provider.DoesNotExist(django.core.exceptions.ObjectDoesNotExist):

The requested object does not exist

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

The query returned multiple objects when only one was expected.

class BackchannelProvider(Provider):
679class BackchannelProvider(Provider):
680    """Base class for providers that augment other providers, for example LDAP and SCIM.
681    Multiple of these providers can be configured per application, they may not use the application
682    slug in URLs as an application may have multiple instances of the same
683    type of Backchannel provider
684
685    They can use the application's policies and metadata"""
686
687    @property
688    def component(self) -> str:
689        raise NotImplementedError
690
691    @property
692    def serializer(self) -> type[Serializer]:
693        raise NotImplementedError
694
695    class Meta:
696        abstract = True

Base class for providers that augment other providers, for example LDAP and SCIM. Multiple of these providers can be configured per application, they may not use the application slug in URLs as an application may have multiple instances of the same type of Backchannel provider

They can use the application's policies and metadata

component: str
687    @property
688    def component(self) -> str:
689        raise NotImplementedError

Return component used to edit this object

serializer: type[rest_framework.serializers.Serializer]
691    @property
692    def serializer(self) -> type[Serializer]:
693        raise NotImplementedError

Get serializer for this model

provider_ptr_id
provider_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 BackchannelProvider.Meta:
695    class Meta:
696        abstract = True
abstract = False
class ApplicationQuerySet(django.db.models.query.QuerySet):
699class ApplicationQuerySet(QuerySet):
700    def with_provider(self) -> QuerySet[Application]:
701        qs = self.select_related("provider")
702        for subclass in Provider.objects.get_queryset()._get_subclasses_recurse(Provider):
703            qs = qs.select_related(f"provider__{subclass}")
704            # Also prefetch/select through each subclass path to ensure casted instances have access
705            qs = qs.prefetch_related(f"provider__{subclass}__property_mappings")
706            qs = qs.select_related(f"provider__{subclass}__application")
707            qs = qs.select_related(f"provider__{subclass}__backchannel_application")
708        return qs

Represent a lazy database lookup for a set of objects.

def with_provider(self) -> django.db.models.query.QuerySet:
700    def with_provider(self) -> QuerySet[Application]:
701        qs = self.select_related("provider")
702        for subclass in Provider.objects.get_queryset()._get_subclasses_recurse(Provider):
703            qs = qs.select_related(f"provider__{subclass}")
704            # Also prefetch/select through each subclass path to ensure casted instances have access
705            qs = qs.prefetch_related(f"provider__{subclass}__property_mappings")
706            qs = qs.select_related(f"provider__{subclass}__application")
707            qs = qs.select_related(f"provider__{subclass}__backchannel_application")
708        return qs
711class Application(SerializerModel, PolicyBindingModel):
712    """Every Application which uses authentik for authentication/identification/authorization
713    needs an Application record. Other authentication types can subclass this Model to
714    add custom fields and other properties"""
715
716    name = models.TextField(help_text=_("Application's display Name."))
717    slug = models.TextField(
718        validators=[validate_slug],
719        help_text=_("Internal application name, used in URLs."),
720        unique=True,
721    )
722    group = models.TextField(blank=True, default="")
723
724    provider = models.OneToOneField(
725        "Provider", null=True, blank=True, default=None, on_delete=models.SET_DEFAULT
726    )
727
728    meta_launch_url = models.TextField(
729        default="", blank=True, validators=[DomainlessFormattedURLValidator()]
730    )
731
732    open_in_new_tab = models.BooleanField(
733        default=False, help_text=_("Open launch URL in a new browser tab or window.")
734    )
735
736    meta_icon = FileField(default="", blank=True)
737    meta_description = models.TextField(default="", blank=True)
738    meta_publisher = models.TextField(default="", blank=True)
739
740    objects = ApplicationQuerySet.as_manager()
741
742    # Reserved slugs that would clash with OAuth2 provider endpoints
743    reserved_slugs = ["authorize", "token", "device", "userinfo", "introspect", "revoke"]
744
745    @property
746    def serializer(self) -> Serializer:
747        from authentik.core.api.applications import ApplicationSerializer
748
749        return ApplicationSerializer
750
751    @property
752    def get_meta_icon(self) -> str | None:
753        """Get the URL to the App Icon image"""
754        if not self.meta_icon:
755            return None
756
757        return get_file_manager(FileUsage.MEDIA).file_url(self.meta_icon)
758
759    @property
760    def get_meta_icon_themed_urls(self) -> dict[str, str] | None:
761        """Get themed URLs for meta_icon if it contains %(theme)s"""
762        if not self.meta_icon:
763            return None
764
765        return get_file_manager(FileUsage.MEDIA).themed_urls(self.meta_icon)
766
767    def get_launch_url(self, user: User | None = None, user_data: dict | None = None) -> str | None:
768        """Get launch URL if set, otherwise attempt to get launch URL based on provider.
769
770        Args:
771            user: User instance for formatting the URL
772            user_data: Pre-serialized user data to avoid re-serialization (performance optimization)
773        """
774        from authentik.core.api.users import UserSerializer
775
776        url = None
777        if self.meta_launch_url:
778            url = self.meta_launch_url
779        elif provider := self.get_provider():
780            url = provider.launch_url
781        if user and url:
782            try:
783                # Use pre-serialized data if available, otherwise serialize now
784                if user_data is None:
785                    user_data = UserSerializer(instance=user).data
786                return url % user_data
787            except Exception as exc:  # noqa
788                LOGGER.warning("Failed to format launch url", exc=exc)
789                return url
790        return url
791
792    def get_provider(self) -> Provider | None:
793        """Get casted provider instance. Needs Application queryset with_provider"""
794        if not self.provider:
795            return None
796        return get_deepest_child(self.provider)
797
798    def backchannel_provider_for[T: Provider](self, provider_type: type[T], **kwargs) -> T | None:
799        """Get Backchannel provider for a specific type"""
800        providers = self.backchannel_providers.filter(
801            **{f"{provider_type._meta.model_name}__isnull": False},
802            **kwargs,
803        )
804        return getattr(providers.first(), provider_type._meta.model_name)
805
806    def __str__(self):
807        return str(self.name)
808
809    class Meta:
810        verbose_name = _("Application")
811        verbose_name_plural = _("Applications")

Every Application which uses authentik for authentication/identification/authorization needs an Application record. Other authentication types can subclass this Model to add custom fields and other properties

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

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

provider

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.

def meta_launch_url(unknown):

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

def open_in_new_tab(unknown):

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

def meta_icon(unknown):

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

def meta_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 meta_publisher(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.

reserved_slugs = ['authorize', 'token', 'device', 'userinfo', 'introspect', 'revoke']
serializer: rest_framework.serializers.Serializer
745    @property
746    def serializer(self) -> Serializer:
747        from authentik.core.api.applications import ApplicationSerializer
748
749        return ApplicationSerializer

Get serializer for this model

get_meta_icon: str | None
751    @property
752    def get_meta_icon(self) -> str | None:
753        """Get the URL to the App Icon image"""
754        if not self.meta_icon:
755            return None
756
757        return get_file_manager(FileUsage.MEDIA).file_url(self.meta_icon)

Get the URL to the App Icon image

get_meta_icon_themed_urls: dict[str, str] | None
759    @property
760    def get_meta_icon_themed_urls(self) -> dict[str, str] | None:
761        """Get themed URLs for meta_icon if it contains %(theme)s"""
762        if not self.meta_icon:
763            return None
764
765        return get_file_manager(FileUsage.MEDIA).themed_urls(self.meta_icon)

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

def get_launch_url( self, user: User | None = None, user_data: dict | None = None) -> str | None:
767    def get_launch_url(self, user: User | None = None, user_data: dict | None = None) -> str | None:
768        """Get launch URL if set, otherwise attempt to get launch URL based on provider.
769
770        Args:
771            user: User instance for formatting the URL
772            user_data: Pre-serialized user data to avoid re-serialization (performance optimization)
773        """
774        from authentik.core.api.users import UserSerializer
775
776        url = None
777        if self.meta_launch_url:
778            url = self.meta_launch_url
779        elif provider := self.get_provider():
780            url = provider.launch_url
781        if user and url:
782            try:
783                # Use pre-serialized data if available, otherwise serialize now
784                if user_data is None:
785                    user_data = UserSerializer(instance=user).data
786                return url % user_data
787            except Exception as exc:  # noqa
788                LOGGER.warning("Failed to format launch url", exc=exc)
789                return url
790        return url

Get launch URL if set, otherwise attempt to get launch URL based on provider.

Args: user: User instance for formatting the URL user_data: Pre-serialized user data to avoid re-serialization (performance optimization)

def get_provider(self) -> Provider | None:
792    def get_provider(self) -> Provider | None:
793        """Get casted provider instance. Needs Application queryset with_provider"""
794        if not self.provider:
795            return None
796        return get_deepest_child(self.provider)

Get casted provider instance. Needs Application queryset with_provider

def backchannel_provider_for(self, provider_type: type[T], **kwargs) -> T | None:
798    def backchannel_provider_for[T: Provider](self, provider_type: type[T], **kwargs) -> T | None:
799        """Get Backchannel provider for a specific type"""
800        providers = self.backchannel_providers.filter(
801            **{f"{provider_type._meta.model_name}__isnull": False},
802            **kwargs,
803        )
804        return getattr(providers.first(), provider_type._meta.model_name)

Get Backchannel provider for a specific type

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

backchannel_providers

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.

applicationentitlement_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_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.

userconsent_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

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

The query returned multiple objects when only one was expected.

814class ApplicationEntitlement(AttributesMixin, SerializerModel, PolicyBindingModel):
815    """Application-scoped entitlement to control authorization in an application"""
816
817    name = models.TextField()
818
819    app = models.ForeignKey(Application, on_delete=models.CASCADE)
820
821    class Meta:
822        verbose_name = _("Application Entitlement")
823        verbose_name_plural = _("Application Entitlements")
824        unique_together = (("app", "name"),)
825
826    def __str__(self):
827        return f"Application Entitlement {self.name} for app {self.app_id}"
828
829    @property
830    def serializer(self) -> type[Serializer]:
831        from authentik.core.api.application_entitlements import ApplicationEntitlementSerializer
832
833        return ApplicationEntitlementSerializer
834
835    def supported_policy_binding_targets(self):
836        return ["group", "user"]

Application-scoped entitlement to control authorization in an application

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.

app

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.

serializer: type[rest_framework.serializers.Serializer]
829    @property
830    def serializer(self) -> type[Serializer]:
831        from authentik.core.api.application_entitlements import ApplicationEntitlementSerializer
832
833        return ApplicationEntitlementSerializer

Get serializer for this model

def supported_policy_binding_targets(self):
835    def supported_policy_binding_targets(self):
836        return ["group", "user"]

Return the list of objects that can be bound to this object.

def attributes(unknown):

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

app_id
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 ApplicationEntitlement.DoesNotExist(authentik.policies.models.PolicyBindingModel.DoesNotExist):

The requested object does not exist

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

The query returned multiple objects when only one was expected.

class SourceUserMatchingModes(django.db.models.enums.TextChoices):
839class SourceUserMatchingModes(models.TextChoices):
840    """Different modes a source can handle new/returning users"""
841
842    IDENTIFIER = "identifier", _("Use the source-specific identifier")
843    EMAIL_LINK = (
844        "email_link",
845        _(
846            "Link to a user with identical email address. Can have security implications "
847            "when a source doesn't validate email addresses."
848        ),
849    )
850    EMAIL_DENY = (
851        "email_deny",
852        _(
853            "Use the user's email address, but deny enrollment when the email address already "
854            "exists."
855        ),
856    )
857    USERNAME_LINK = (
858        "username_link",
859        _(
860            "Link to a user with identical username. Can have security implications "
861            "when a username is used with another source."
862        ),
863    )
864    USERNAME_DENY = (
865        "username_deny",
866        _("Use the user's username, but deny enrollment when the username already exists."),
867    )

Different modes a source can handle new/returning users

class SourceGroupMatchingModes(django.db.models.enums.TextChoices):
870class SourceGroupMatchingModes(models.TextChoices):
871    """Different modes a source can handle new/returning groups"""
872
873    IDENTIFIER = "identifier", _("Use the source-specific identifier")
874    NAME_LINK = (
875        "name_link",
876        _(
877            "Link to a group with identical name. Can have security implications "
878            "when a group name is used with another source."
879        ),
880    )
881    NAME_DENY = (
882        "name_deny",
883        _("Use the group name, but deny enrollment when the name already exists."),
884    )

Different modes a source can handle new/returning groups

 887class Source(ManagedModel, SerializerModel, PolicyBindingModel):
 888    """Base Authentication source, i.e. an OAuth Provider, SAML Remote or LDAP Server"""
 889
 890    MANAGED_INBUILT = "goauthentik.io/sources/inbuilt"
 891
 892    name = models.TextField(help_text=_("Source's display Name."))
 893    slug = models.TextField(
 894        validators=[validate_slug],
 895        help_text=_("Internal source name, used in URLs."),
 896        unique=True,
 897    )
 898
 899    user_path_template = models.TextField(default="goauthentik.io/sources/%(slug)s")
 900
 901    enabled = models.BooleanField(default=True)
 902    promoted = models.BooleanField(
 903        default=False,
 904        help_text=_(
 905            "When enabled, this source will be displayed as a prominent button on the "
 906            "login page, instead of a small icon."
 907        ),
 908    )
 909    user_property_mappings = models.ManyToManyField(
 910        "PropertyMapping", default=None, blank=True, related_name="source_userpropertymappings_set"
 911    )
 912    group_property_mappings = models.ManyToManyField(
 913        "PropertyMapping", default=None, blank=True, related_name="source_grouppropertymappings_set"
 914    )
 915
 916    icon = FileField(blank=True, default="")
 917
 918    authentication_flow = models.ForeignKey(
 919        "authentik_flows.Flow",
 920        blank=True,
 921        null=True,
 922        default=None,
 923        on_delete=models.SET_NULL,
 924        help_text=_("Flow to use when authenticating existing users."),
 925        related_name="source_authentication",
 926    )
 927    enrollment_flow = models.ForeignKey(
 928        "authentik_flows.Flow",
 929        blank=True,
 930        null=True,
 931        default=None,
 932        on_delete=models.SET_NULL,
 933        help_text=_("Flow to use when enrolling new users."),
 934        related_name="source_enrollment",
 935    )
 936
 937    user_matching_mode = models.TextField(
 938        choices=SourceUserMatchingModes.choices,
 939        default=SourceUserMatchingModes.IDENTIFIER,
 940        help_text=_(
 941            "How the source determines if an existing user should be authenticated or "
 942            "a new user enrolled."
 943        ),
 944    )
 945    group_matching_mode = models.TextField(
 946        choices=SourceGroupMatchingModes.choices,
 947        default=SourceGroupMatchingModes.IDENTIFIER,
 948        help_text=_(
 949            "How the source determines if an existing group should be used or a new group created."
 950        ),
 951    )
 952
 953    objects = InheritanceManager()
 954
 955    @property
 956    def icon_url(self) -> str | None:
 957        """Get the URL to the source icon"""
 958        if not self.icon:
 959            return None
 960
 961        return get_file_manager(FileUsage.MEDIA).file_url(self.icon)
 962
 963    @property
 964    def icon_themed_urls(self) -> dict[str, str] | None:
 965        """Get themed URLs for icon if it contains %(theme)s"""
 966        if not self.icon:
 967            return None
 968
 969        return get_file_manager(FileUsage.MEDIA).themed_urls(self.icon)
 970
 971    def get_user_path(self) -> str:
 972        """Get user path, fallback to default for formatting errors"""
 973        try:
 974            return self.user_path_template % {
 975                "slug": self.slug,
 976            }
 977
 978        except Exception as exc:  # noqa
 979            LOGGER.warning("Failed to template user path", exc=exc, source=self)
 980            return User.default_path()
 981
 982    @property
 983    def component(self) -> str:
 984        """Return component used to edit this object"""
 985        if self.managed == self.MANAGED_INBUILT:
 986            return ""
 987        raise NotImplementedError
 988
 989    @property
 990    def property_mapping_type(self) -> type[PropertyMapping]:
 991        """Return property mapping type used by this object"""
 992        if self.managed == self.MANAGED_INBUILT:
 993            from authentik.core.models import PropertyMapping
 994
 995            return PropertyMapping
 996        raise NotImplementedError
 997
 998    def ui_login_button(self, request: HttpRequest) -> UILoginButton | None:
 999        """If source uses a http-based flow, return UI Information about the login
1000        button. If source doesn't use http-based flow, return None."""
1001        return None
1002
1003    def ui_user_settings(self) -> UserSettingSerializer | None:
1004        """Entrypoint to integrate with User settings. Can either return None if no
1005        user settings are available, or UserSettingSerializer."""
1006        return None
1007
1008    def get_base_user_properties(self, **kwargs) -> dict[str, Any | dict[str, Any]]:
1009        """Get base properties for a user to build final properties upon."""
1010        if self.managed == self.MANAGED_INBUILT:
1011            return {}
1012        raise NotImplementedError
1013
1014    def get_base_group_properties(self, **kwargs) -> dict[str, Any | dict[str, Any]]:
1015        """Get base properties for a group to build final properties upon."""
1016        if self.managed == self.MANAGED_INBUILT:
1017            return {}
1018        raise NotImplementedError
1019
1020    def __str__(self):
1021        return str(self.name)
1022
1023    class Meta:
1024        indexes = [
1025            models.Index(
1026                fields=[
1027                    "slug",
1028                ]
1029            ),
1030            models.Index(
1031                fields=[
1032                    "name",
1033                ]
1034            ),
1035            models.Index(
1036                fields=[
1037                    "enabled",
1038                ]
1039            ),
1040        ]

Base Authentication source, i.e. an OAuth Provider, SAML Remote or LDAP Server

MANAGED_INBUILT = 'goauthentik.io/sources/inbuilt'
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 user_path_template(unknown):

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

def enabled(unknown):

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

def promoted(unknown):

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

user_property_mappings

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.

group_property_mappings

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

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

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

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

The type of the None singleton.

icon_url: str | None
955    @property
956    def icon_url(self) -> str | None:
957        """Get the URL to the source icon"""
958        if not self.icon:
959            return None
960
961        return get_file_manager(FileUsage.MEDIA).file_url(self.icon)

Get the URL to the source icon

icon_themed_urls: dict[str, str] | None
963    @property
964    def icon_themed_urls(self) -> dict[str, str] | None:
965        """Get themed URLs for icon if it contains %(theme)s"""
966        if not self.icon:
967            return None
968
969        return get_file_manager(FileUsage.MEDIA).themed_urls(self.icon)

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

def get_user_path(self) -> str:
971    def get_user_path(self) -> str:
972        """Get user path, fallback to default for formatting errors"""
973        try:
974            return self.user_path_template % {
975                "slug": self.slug,
976            }
977
978        except Exception as exc:  # noqa
979            LOGGER.warning("Failed to template user path", exc=exc, source=self)
980            return User.default_path()

Get user path, fallback to default for formatting errors

component: str
982    @property
983    def component(self) -> str:
984        """Return component used to edit this object"""
985        if self.managed == self.MANAGED_INBUILT:
986            return ""
987        raise NotImplementedError

Return component used to edit this object

property_mapping_type: type[PropertyMapping]
989    @property
990    def property_mapping_type(self) -> type[PropertyMapping]:
991        """Return property mapping type used by this object"""
992        if self.managed == self.MANAGED_INBUILT:
993            from authentik.core.models import PropertyMapping
994
995            return PropertyMapping
996        raise NotImplementedError

Return property mapping type used by this object

def ui_login_button( self, request: django.http.request.HttpRequest) -> authentik.core.types.UILoginButton | None:
 998    def ui_login_button(self, request: HttpRequest) -> UILoginButton | None:
 999        """If source uses a http-based flow, return UI Information about the login
1000        button. If source doesn't use http-based flow, return None."""
1001        return None

If source uses a http-based flow, return UI Information about the login button. If source doesn't use http-based flow, return None.

def ui_user_settings(self) -> authentik.core.types.UserSettingSerializer | None:
1003    def ui_user_settings(self) -> UserSettingSerializer | None:
1004        """Entrypoint to integrate with User settings. Can either return None if no
1005        user settings are available, or UserSettingSerializer."""
1006        return None

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

def get_base_user_properties(self, **kwargs) -> dict[str, typing.Any | dict[str, typing.Any]]:
1008    def get_base_user_properties(self, **kwargs) -> dict[str, Any | dict[str, Any]]:
1009        """Get base properties for a user to build final properties upon."""
1010        if self.managed == self.MANAGED_INBUILT:
1011            return {}
1012        raise NotImplementedError

Get base properties for a user to build final properties upon.

def get_base_group_properties(self, **kwargs) -> dict[str, typing.Any | dict[str, typing.Any]]:
1014    def get_base_group_properties(self, **kwargs) -> dict[str, Any | dict[str, Any]]:
1015        """Get base properties for a group to build final properties upon."""
1016        if self.managed == self.MANAGED_INBUILT:
1017            return {}
1018        raise NotImplementedError

Get base properties for a group to build final properties upon.

def managed(unknown):

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

authentication_flow_id
enrollment_flow_id
def get_user_matching_mode_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_group_matching_mode_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.

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

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

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

oauthsource

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.

samlsource

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.

kerberossource

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.

ldapsource

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

plexsource

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.

scimsource

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.

telegramsource

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

1043class UserSourceConnection(SerializerModel, CreatedUpdatedModel):
1044    """Connection between User and Source."""
1045
1046    user = models.ForeignKey(User, on_delete=models.CASCADE)
1047    source = models.ForeignKey(Source, on_delete=models.CASCADE)
1048    identifier = models.TextField()
1049
1050    objects = InheritanceManager()
1051
1052    @property
1053    def serializer(self) -> type[Serializer]:
1054        """Get serializer for this model"""
1055        raise NotImplementedError
1056
1057    def __str__(self) -> str:
1058        return f"User-source connection (user={self.user_id}, source={self.source_id})"
1059
1060    class Meta:
1061        unique_together = (("user", "source"),)
1062        indexes = (
1063            models.Index(fields=("identifier",)),
1064            models.Index(fields=("source", "identifier")),
1065        )

Connection between User and Source.

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.

source

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 identifier(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.Serializer]
1052    @property
1053    def serializer(self) -> type[Serializer]:
1054        """Get serializer for this model"""
1055        raise NotImplementedError

Get serializer for this model

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

useroauthsourceconnection

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.

usersamlsourceconnection

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.

userkerberossourceconnection

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.

userldapsourceconnection

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.

userplexsourceconnection

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.

usertelegramsourceconnection

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 UserSourceConnection.DoesNotExist(django.core.exceptions.ObjectDoesNotExist):

The requested object does not exist

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

The query returned multiple objects when only one was expected.

1068class GroupSourceConnection(SerializerModel, CreatedUpdatedModel):
1069    """Connection between Group and Source."""
1070
1071    group = models.ForeignKey(Group, on_delete=models.CASCADE)
1072    source = models.ForeignKey(Source, on_delete=models.CASCADE)
1073    identifier = models.TextField()
1074
1075    objects = InheritanceManager()
1076
1077    @property
1078    def serializer(self) -> type[Serializer]:
1079        """Get serializer for this model"""
1080        raise NotImplementedError
1081
1082    def __str__(self) -> str:
1083        return f"Group-source connection (group={self.group_id}, source={self.source_id})"
1084
1085    class Meta:
1086        unique_together = (("group", "source"),)

Connection between Group and Source.

group

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.

source

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 identifier(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.Serializer]
1077    @property
1078    def serializer(self) -> type[Serializer]:
1079        """Get serializer for this model"""
1080        raise NotImplementedError

Get serializer for this model

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.

group_id
source_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.

groupoauthsourceconnection

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.

groupsamlsourceconnection

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.

groupkerberossourceconnection

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.

groupldapsourceconnection

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.

groupplexsourceconnection

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.

grouptelegramsourceconnection

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 GroupSourceConnection.DoesNotExist(django.core.exceptions.ObjectDoesNotExist):

The requested object does not exist

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

The query returned multiple objects when only one was expected.

class ExpiringManager(django.db.models.manager.Manager):
1089class ExpiringManager(Manager):
1090    """Manager for expiring objects which filters out expired objects by default"""
1091
1092    def get_queryset(self):
1093        return QuerySet(self.model, using=self._db).exclude(expires__lt=now(), expiring=True)
1094
1095    def including_expired(self):
1096        return QuerySet(self.model, using=self._db)

Manager for expiring objects which filters out expired objects by default

def get_queryset(self):
1092    def get_queryset(self):
1093        return QuerySet(self.model, using=self._db).exclude(expires__lt=now(), expiring=True)

Return a new QuerySet object. Subclasses can override this method to customize the behavior of the Manager.

def including_expired(self):
1095    def including_expired(self):
1096        return QuerySet(self.model, using=self._db)
class ExpiringModel(django.db.models.base.Model):
1099class ExpiringModel(models.Model):
1100    """Base Model which can expire, and is automatically cleaned up."""
1101
1102    expires = models.DateTimeField(default=None, null=True)
1103    expiring = models.BooleanField(default=True)
1104
1105    objects = ExpiringManager()
1106
1107    class Meta:
1108        abstract = True
1109        indexes = [
1110            models.Index(fields=["expires"]),
1111            models.Index(fields=["expiring"]),
1112            models.Index(fields=["expiring", "expires"]),
1113        ]
1114
1115    def expire_action(self, *args, **kwargs):
1116        """Handler which is called when this object is expired. By
1117        default the object is deleted. This is less efficient compared
1118        to bulk deleting objects, but classes like Token() need to change
1119        values instead of being deleted."""
1120        try:
1121            return self.delete(*args, **kwargs)
1122        except self.DoesNotExist:
1123            # Object has already been deleted, so this should be fine
1124            return None
1125
1126    @classmethod
1127    def filter_not_expired(cls, **kwargs) -> QuerySet[Self]:
1128        """Filer for tokens which are not expired yet or are not expiring,
1129        and match filters in `kwargs`"""
1130        from authentik.events.models import Event
1131
1132        deprecation_id = f"{class_to_path(cls)}.filter_not_expired"
1133
1134        Event.log_deprecation(
1135            deprecation_id,
1136            message=(
1137                ".filter_not_expired() is deprecated as the default lookup now excludes "
1138                "expired objects."
1139            ),
1140        )
1141
1142        for obj in (
1143            cls.objects.including_expired()
1144            .filter(**kwargs)
1145            .filter(Q(expires__lt=now(), expiring=True))
1146        ):
1147            obj.delete()
1148        return cls.objects.filter(**kwargs)
1149
1150    @property
1151    def is_expired(self) -> bool:
1152        """Check if token is expired yet."""
1153        if not self.expiring:
1154            return False
1155        return now() > self.expires

Base Model which can expire, and is automatically cleaned up.

def expires(unknown):

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

def expiring(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.

def expire_action(self, *args, **kwargs):
1115    def expire_action(self, *args, **kwargs):
1116        """Handler which is called when this object is expired. By
1117        default the object is deleted. This is less efficient compared
1118        to bulk deleting objects, but classes like Token() need to change
1119        values instead of being deleted."""
1120        try:
1121            return self.delete(*args, **kwargs)
1122        except self.DoesNotExist:
1123            # Object has already been deleted, so this should be fine
1124            return None

Handler which is called when this object is expired. By default the object is deleted. This is less efficient compared to bulk deleting objects, but classes like Token() need to change values instead of being deleted.

@classmethod
def filter_not_expired(cls, **kwargs) -> django.db.models.query.QuerySet:
1126    @classmethod
1127    def filter_not_expired(cls, **kwargs) -> QuerySet[Self]:
1128        """Filer for tokens which are not expired yet or are not expiring,
1129        and match filters in `kwargs`"""
1130        from authentik.events.models import Event
1131
1132        deprecation_id = f"{class_to_path(cls)}.filter_not_expired"
1133
1134        Event.log_deprecation(
1135            deprecation_id,
1136            message=(
1137                ".filter_not_expired() is deprecated as the default lookup now excludes "
1138                "expired objects."
1139            ),
1140        )
1141
1142        for obj in (
1143            cls.objects.including_expired()
1144            .filter(**kwargs)
1145            .filter(Q(expires__lt=now(), expiring=True))
1146        ):
1147            obj.delete()
1148        return cls.objects.filter(**kwargs)

Filer for tokens which are not expired yet or are not expiring, and match filters in kwargs

is_expired: bool
1150    @property
1151    def is_expired(self) -> bool:
1152        """Check if token is expired yet."""
1153        if not self.expiring:
1154            return False
1155        return now() > self.expires

Check if token is expired yet.

class ExpiringModel.Meta:
1107    class Meta:
1108        abstract = True
1109        indexes = [
1110            models.Index(fields=["expires"]),
1111            models.Index(fields=["expiring"]),
1112            models.Index(fields=["expiring", "expires"]),
1113        ]
abstract = False
indexes = [<Index: fields=['expires']>, <Index: fields=['expiring']>, <Index: fields=['expiring', 'expires']>]
class TokenIntents(django.db.models.enums.TextChoices):
1158class TokenIntents(models.TextChoices):
1159    """Intents a Token can be created for."""
1160
1161    # Single use token
1162    INTENT_VERIFICATION = "verification"
1163
1164    # Allow access to API
1165    INTENT_API = "api"
1166
1167    # Recovery use for the recovery app
1168    INTENT_RECOVERY = "recovery"
1169
1170    # App-specific passwords
1171    INTENT_APP_PASSWORD = "app_password"  # nosec

Intents a Token can be created for.

INTENT_VERIFICATION = TokenIntents.INTENT_VERIFICATION
INTENT_RECOVERY = TokenIntents.INTENT_RECOVERY
INTENT_APP_PASSWORD = TokenIntents.INTENT_APP_PASSWORD
1174class Token(SerializerModel, ManagedModel, ExpiringModel):
1175    """Token used to authenticate the User for API Access or confirm another Stage like Email."""
1176
1177    token_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4)
1178    identifier = models.SlugField(max_length=255, unique=True)
1179    key = models.TextField(default=default_token_key)
1180    intent = models.TextField(
1181        choices=TokenIntents.choices, default=TokenIntents.INTENT_VERIFICATION
1182    )
1183    user = models.ForeignKey("User", on_delete=models.CASCADE, related_name="+")
1184    description = models.TextField(default="", blank=True)
1185
1186    class Meta:
1187        verbose_name = _("Token")
1188        verbose_name_plural = _("Tokens")
1189        indexes = ExpiringModel.Meta.indexes + [
1190            models.Index(fields=["identifier"]),
1191            models.Index(fields=["key"]),
1192        ]
1193        permissions = [
1194            ("view_token_key", _("View token's key")),
1195            ("set_token_key", _("Set a token's key")),
1196        ]
1197
1198    def __str__(self):
1199        description = f"{self.identifier}"
1200        if self.expiring:
1201            description += f" (expires={self.expires})"
1202        return description
1203
1204    @property
1205    def serializer(self) -> type[Serializer]:
1206        from authentik.core.api.tokens import TokenSerializer
1207
1208        return TokenSerializer
1209
1210    def expire_action(self, *args, **kwargs):
1211        """Handler which is called when this object is expired."""
1212        from authentik.events.models import Event, EventAction
1213
1214        if self.intent in [
1215            TokenIntents.INTENT_RECOVERY,
1216            TokenIntents.INTENT_VERIFICATION,
1217            TokenIntents.INTENT_APP_PASSWORD,
1218        ]:
1219            super().expire_action(*args, **kwargs)
1220            return
1221
1222        self.key = default_token_key()
1223        self.expires = default_token_duration()
1224        self.save(*args, **kwargs)
1225        Event.new(
1226            action=EventAction.SECRET_ROTATE,
1227            token=self,
1228            message=f"Token {self.identifier}'s secret was rotated.",
1229        ).save()

Token used to authenticate the User for API Access or confirm another Stage like Email.

def token_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 identifier(unknown):

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

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

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

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 description(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.Serializer]
1204    @property
1205    def serializer(self) -> type[Serializer]:
1206        from authentik.core.api.tokens import TokenSerializer
1207
1208        return TokenSerializer

Get serializer for this model

def expire_action(self, *args, **kwargs):
1210    def expire_action(self, *args, **kwargs):
1211        """Handler which is called when this object is expired."""
1212        from authentik.events.models import Event, EventAction
1213
1214        if self.intent in [
1215            TokenIntents.INTENT_RECOVERY,
1216            TokenIntents.INTENT_VERIFICATION,
1217            TokenIntents.INTENT_APP_PASSWORD,
1218        ]:
1219            super().expire_action(*args, **kwargs)
1220            return
1221
1222        self.key = default_token_key()
1223        self.expires = default_token_duration()
1224        self.save(*args, **kwargs)
1225        Event.new(
1226            action=EventAction.SECRET_ROTATE,
1227            token=self,
1228            message=f"Token {self.identifier}'s secret was rotated.",
1229        ).save()

Handler which is called when this object is expired.

def managed(unknown):

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

def expires(unknown):

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

def expiring(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_intent_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.

user_id
flowtoken

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.

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

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

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

The requested object does not exist

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

The query returned multiple objects when only one was expected.

1232class PropertyMapping(SerializerModel, ManagedModel):
1233    """User-defined key -> x mapping which can be used by providers to expose extra data."""
1234
1235    pm_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4)
1236    name = models.TextField(unique=True)
1237    expression = models.TextField()
1238
1239    objects = InheritanceManager()
1240
1241    @property
1242    def component(self) -> str:
1243        """Return component used to edit this object"""
1244        raise NotImplementedError
1245
1246    @property
1247    def serializer(self) -> type[Serializer]:
1248        """Get serializer for this model"""
1249        raise NotImplementedError
1250
1251    def evaluate(self, user: User | None, request: HttpRequest | None, **kwargs) -> Any:
1252        """Evaluate `self.expression` using `**kwargs` as Context."""
1253        from authentik.core.expression.evaluator import PropertyMappingEvaluator
1254
1255        evaluator = PropertyMappingEvaluator(self, user, request, **kwargs)
1256        try:
1257            return evaluator.evaluate(self.expression)
1258        except ControlFlowException as exc:
1259            raise exc
1260        except Exception as exc:
1261            raise PropertyMappingExpressionException(exc, self) from exc
1262
1263    def __str__(self):
1264        return f"Property Mapping {self.name}"
1265
1266    class Meta:
1267        verbose_name = _("Property Mapping")
1268        verbose_name_plural = _("Property Mappings")

User-defined key -> x mapping which can be used by providers to expose extra data.

def pm_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 expression(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.

component: str
1241    @property
1242    def component(self) -> str:
1243        """Return component used to edit this object"""
1244        raise NotImplementedError

Return component used to edit this object

serializer: type[rest_framework.serializers.Serializer]
1246    @property
1247    def serializer(self) -> type[Serializer]:
1248        """Get serializer for this model"""
1249        raise NotImplementedError

Get serializer for this model

def evaluate( self, user: User | None, request: django.http.request.HttpRequest | None, **kwargs) -> Any:
1251    def evaluate(self, user: User | None, request: HttpRequest | None, **kwargs) -> Any:
1252        """Evaluate `self.expression` using `**kwargs` as Context."""
1253        from authentik.core.expression.evaluator import PropertyMappingEvaluator
1254
1255        evaluator = PropertyMappingEvaluator(self, user, request, **kwargs)
1256        try:
1257            return evaluator.evaluate(self.expression)
1258        except ControlFlowException as exc:
1259            raise exc
1260        except Exception as exc:
1261            raise PropertyMappingExpressionException(exc, self) from exc

Evaluate self.expression using **kwargs as Context.

def managed(unknown):

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

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

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

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

notificationwebhookmapping

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.

oauthsourcepropertymapping

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.

scopemapping

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.

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

racpropertymapping

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.

radiusproviderpropertymapping

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.

samlsourcepropertymapping

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.

samlpropertymapping

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.

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

scimmapping

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.

kerberossourcepropertymapping

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.

ldapsourcepropertymapping

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.

plexsourcepropertymapping

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.

scimsourcepropertymapping

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.

telegramsourcepropertymapping

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.

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

googleworkspaceprovidermapping

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.

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

microsoftentraprovidermapping

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 PropertyMapping.DoesNotExist(django.core.exceptions.ObjectDoesNotExist):

The requested object does not exist

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

The query returned multiple objects when only one was expected.

class Session(ExpiringModel, django.contrib.sessions.base_session.AbstractBaseSession):
1271class Session(ExpiringModel, AbstractBaseSession):
1272    """User session with extra fields for fast access"""
1273
1274    # Remove upstream field because we're using our own ExpiringModel
1275    expire_date = None
1276    session_data = models.BinaryField(_("session data"))
1277
1278    # Keep in sync with Session.Keys
1279    last_ip = models.GenericIPAddressField()
1280    last_user_agent = models.TextField(blank=True)
1281    last_used = models.DateTimeField(auto_now=True)
1282
1283    class Meta:
1284        verbose_name = _("Session")
1285        verbose_name_plural = _("Sessions")
1286        indexes = ExpiringModel.Meta.indexes + [
1287            models.Index(fields=["expires", "session_key"]),
1288        ]
1289        default_permissions = []
1290
1291    def __str__(self):
1292        return self.session_key
1293
1294    class Keys(StrEnum):
1295        """
1296        Keys to be set with the session interface for the fields above to be updated.
1297
1298        If a field is added here that needs to be initialized when the session is initialized,
1299        it must also be reflected in authentik.root.middleware.SessionMiddleware.process_request
1300        and in authentik.core.sessions.SessionStore.__init__
1301        """
1302
1303        LAST_IP = "last_ip"
1304        LAST_USER_AGENT = "last_user_agent"
1305        LAST_USED = "last_used"
1306
1307    @classmethod
1308    def get_session_store_class(cls):
1309        from authentik.core.sessions import SessionStore
1310
1311        return SessionStore
1312
1313    def get_decoded(self):
1314        raise NotImplementedError

User session with extra fields for fast access

expire_date = None
def session_data(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_ip(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_user_agent(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.

@classmethod
def get_session_store_class(cls):
1307    @classmethod
1308    def get_session_store_class(cls):
1309        from authentik.core.sessions import SessionStore
1310
1311        return SessionStore
def get_decoded(self):
1313    def get_decoded(self):
1314        raise NotImplementedError
def expires(unknown):

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

def expiring(unknown):

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

def session_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 get_next_by_last_used(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_used(unknown):

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

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

authenticatedsession

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 Session.Keys(enum.StrEnum):
1294    class Keys(StrEnum):
1295        """
1296        Keys to be set with the session interface for the fields above to be updated.
1297
1298        If a field is added here that needs to be initialized when the session is initialized,
1299        it must also be reflected in authentik.root.middleware.SessionMiddleware.process_request
1300        and in authentik.core.sessions.SessionStore.__init__
1301        """
1302
1303        LAST_IP = "last_ip"
1304        LAST_USER_AGENT = "last_user_agent"
1305        LAST_USED = "last_used"

Keys to be set with the session interface for the fields above to be updated.

If a field is added here that needs to be initialized when the session is initialized, it must also be reflected in authentik.root.middleware.SessionMiddleware.process_request and in authentik.core.sessions.SessionStore.__init__

LAST_IP = <Keys.LAST_IP: 'last_ip'>
LAST_USER_AGENT = <Keys.LAST_USER_AGENT: 'last_user_agent'>
LAST_USED = <Keys.LAST_USED: 'last_used'>
class Session.DoesNotExist(django.core.exceptions.ObjectDoesNotExist):

The requested object does not exist

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

The query returned multiple objects when only one was expected.

class AuthenticatedSession(authentik.lib.models.SerializerModel):
1317class AuthenticatedSession(SerializerModel):
1318    session = models.OneToOneField(Session, on_delete=models.CASCADE, primary_key=True)
1319    # We use the session as primary key, but we need the API to be able to reference
1320    # this object uniquely without exposing the session key
1321    uuid = models.UUIDField(default=uuid4, unique=True)
1322
1323    user = models.ForeignKey(User, on_delete=models.CASCADE)
1324
1325    @property
1326    def serializer(self) -> type[Serializer]:
1327        from authentik.core.api.authenticated_sessions import AuthenticatedSessionSerializer
1328
1329        return AuthenticatedSessionSerializer
1330
1331    class Meta:
1332        verbose_name = _("Authenticated Session")
1333        verbose_name_plural = _("Authenticated Sessions")
1334
1335    def __str__(self) -> str:
1336        return f"Authenticated Session {str(self.pk)[:10]}"
1337
1338    @staticmethod
1339    def from_request(request: HttpRequest, user: User) -> AuthenticatedSession | None:
1340        """Create a new session from a http request"""
1341        if not hasattr(request, "session") or not request.session.exists(
1342            request.session.session_key
1343        ):
1344            return None
1345        return AuthenticatedSession(
1346            session=Session.objects.filter(session_key=request.session.session_key).first(),
1347            user=user,
1348        )

AuthenticatedSession(session, uuid, user)

session

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.

def uuid(unknown):

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

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.

serializer: type[rest_framework.serializers.Serializer]
1325    @property
1326    def serializer(self) -> type[Serializer]:
1327        from authentik.core.api.authenticated_sessions import AuthenticatedSessionSerializer
1328
1329        return AuthenticatedSessionSerializer

Get serializer for this model

@staticmethod
def from_request( request: django.http.request.HttpRequest, user: User) -> AuthenticatedSession | None:
1338    @staticmethod
1339    def from_request(request: HttpRequest, user: User) -> AuthenticatedSession | None:
1340        """Create a new session from a http request"""
1341        if not hasattr(request, "session") or not request.session.exists(
1342            request.session.session_key
1343        ):
1344            return None
1345        return AuthenticatedSession(
1346            session=Session.objects.filter(session_key=request.session.session_key).first(),
1347            user=user,
1348        )

Create a new session from a http request

session_id
user_id
def objects(unknown):

The type of the None singleton.

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

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

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

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

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

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

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

The requested object does not exist

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

The query returned multiple objects when only one was expected.