authentik.root.settings

root settings for authentik

  1"""root settings for authentik"""
  2
  3import importlib
  4from collections import OrderedDict
  5from hashlib import sha512
  6from pathlib import Path
  7
  8import orjson
  9from django.utils import http as utils_http
 10from sentry_sdk import set_tag
 11from xmlsec import enable_debug_trace
 12
 13from authentik import authentik_version
 14from authentik.lib.config import CONFIG, django_db_config
 15from authentik.lib.logging import get_logger_config, structlog_configure
 16from authentik.lib.sentry import sentry_init
 17from authentik.lib.utils.reflection import get_env
 18from authentik.lib.utils.time import timedelta_from_string
 19from authentik.stages.password import BACKEND_APP_PASSWORD, BACKEND_INBUILT, BACKEND_LDAP
 20
 21BASE_DIR = Path(__file__).absolute().parent.parent.parent
 22
 23DEBUG = CONFIG.get_bool("debug")
 24SECRET_KEY = CONFIG.get("secret_key")
 25
 26INTERNAL_IPS = ["127.0.0.1"]
 27ALLOWED_HOSTS = ["*"]
 28SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
 29SECURE_CROSS_ORIGIN_OPENER_POLICY = None
 30LOGIN_URL = "authentik_flows:default-authentication"
 31
 32# Custom user model
 33AUTH_USER_MODEL = "authentik_core.User"
 34
 35CSRF_COOKIE_PATH = LANGUAGE_COOKIE_PATH = SESSION_COOKIE_PATH = CONFIG.get("web.path", "/")
 36
 37CSRF_COOKIE_NAME = "authentik_csrf"
 38CSRF_HEADER_NAME = "HTTP_X_AUTHENTIK_CSRF"
 39LANGUAGE_COOKIE_NAME = "authentik_language"
 40SESSION_COOKIE_NAME = "authentik_session"
 41SESSION_COOKIE_DOMAIN = CONFIG.get("cookie_domain", None)
 42APPEND_SLASH = False
 43
 44AUTHENTICATION_BACKENDS = [
 45    BACKEND_INBUILT,
 46    BACKEND_APP_PASSWORD,
 47    BACKEND_LDAP,
 48    "guardian.backends.ObjectPermissionBackend",
 49]
 50
 51DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
 52
 53# Application definition
 54SHARED_APPS = [
 55    "authentik.commands",
 56    "django_tenants",
 57    "authentik.tenants",
 58    "django.contrib.messages",
 59    "django.contrib.staticfiles",
 60    "django.contrib.humanize",
 61    "django.contrib.postgres",
 62    "psqlextra",
 63    "rest_framework",
 64    "django_filters",
 65    "drf_spectacular",
 66    "django_prometheus",
 67    "django_countries",
 68    "pgactivity",
 69    "pglock",
 70    "channels",
 71    "django_channels_postgres",
 72    "django_dramatiq_postgres",
 73    "authentik.tasks",
 74]
 75TENANT_APPS = [
 76    "django.contrib.auth",
 77    "django.contrib.contenttypes",
 78    "django.contrib.sessions",
 79    "pgtrigger",
 80    "django_postgres_cache",
 81    "authentik.admin",
 82    "authentik.api",
 83    "authentik.core",
 84    "authentik.crypto",
 85    "authentik.endpoints",
 86    "authentik.endpoints.connectors.agent",
 87    "authentik.events",
 88    "authentik.admin.files",
 89    "authentik.flows",
 90    "authentik.outposts",
 91    "authentik.policies.dummy",
 92    "authentik.policies.event_matcher",
 93    "authentik.policies.expiry",
 94    "authentik.policies.expression",
 95    "authentik.policies.geoip",
 96    "authentik.policies.password",
 97    "authentik.policies.reputation",
 98    "authentik.policies",
 99    "authentik.providers.ldap",
100    "authentik.providers.oauth2",
101    "authentik.providers.proxy",
102    "authentik.providers.rac",
103    "authentik.providers.radius",
104    "authentik.providers.saml",
105    "authentik.providers.scim",
106    "authentik.rbac",
107    "authentik.recovery",
108    "authentik.sources.kerberos",
109    "authentik.sources.ldap",
110    "authentik.sources.oauth",
111    "authentik.sources.plex",
112    "authentik.sources.saml",
113    "authentik.sources.scim",
114    "authentik.sources.telegram",
115    "authentik.stages.authenticator",
116    "authentik.stages.authenticator_duo",
117    "authentik.stages.authenticator_email",
118    "authentik.stages.authenticator_sms",
119    "authentik.stages.authenticator_static",
120    "authentik.stages.authenticator_totp",
121    "authentik.stages.authenticator_validate",
122    "authentik.stages.authenticator_webauthn",
123    "authentik.stages.captcha",
124    "authentik.stages.consent",
125    "authentik.stages.deny",
126    "authentik.stages.dummy",
127    "authentik.stages.email",
128    "authentik.stages.identification",
129    "authentik.stages.invitation",
130    "authentik.stages.password",
131    "authentik.stages.prompt",
132    "authentik.stages.redirect",
133    "authentik.stages.user_delete",
134    "authentik.stages.user_login",
135    "authentik.stages.user_logout",
136    "authentik.stages.user_write",
137    "authentik.tasks.schedules",
138    "authentik.brands",
139    "authentik.blueprints",
140    "guardian",
141]
142
143TENANT_MODEL = "authentik_tenants.Tenant"
144TENANT_DOMAIN_MODEL = "authentik_tenants.Domain"
145
146TENANT_CREATION_FAKES_MIGRATIONS = True
147TENANT_BASE_SCHEMA = "template"
148PUBLIC_SCHEMA_NAME = CONFIG.get("postgresql.default_schema")
149
150GUARDIAN_GROUP_MODEL = "authentik_core.Group"
151GUARDIAN_ROLE_MODEL = "authentik_rbac.Role"
152
153SPECTACULAR_SETTINGS = {
154    "TITLE": "authentik",
155    "DESCRIPTION": "Making authentication simple.",
156    "VERSION": authentik_version(),
157    "COMPONENT_SPLIT_REQUEST": True,
158    "SCHEMA_PATH_PREFIX": "/api/v([0-9]+(beta)?)",
159    "SCHEMA_PATH_PREFIX_TRIM": True,
160    "SERVERS": [
161        {
162            "url": "/api/v3",
163        },
164    ],
165    "CONTACT": {
166        "email": "hello@goauthentik.io",
167    },
168    "AUTHENTICATION_WHITELIST": ["authentik.api.authentication.TokenAuthentication"],
169    "LICENSE": {
170        "name": "MIT",
171        "url": "https://github.com/goauthentik/authentik/blob/main/LICENSE",
172    },
173    "ENUM_NAME_OVERRIDES": {
174        "AppEnum": "authentik.lib.api.Apps",
175        "ConsentModeEnum": "authentik.stages.consent.models.ConsentMode",
176        "CountryCodeEnum": "django_countries.countries",
177        "DeviceClassesEnum": "authentik.stages.authenticator_validate.models.DeviceClasses",
178        "DeviceFactsOSFamily": "authentik.endpoints.facts.OSFamily",
179        "EventActions": "authentik.events.models.EventAction",
180        "FlowDesignationEnum": "authentik.flows.models.FlowDesignation",
181        "FlowLayoutEnum": "authentik.flows.models.FlowLayout",
182        "LDAPAPIAccessMode": "authentik.providers.ldap.models.APIAccessMode",
183        "ModelEnum": "authentik.lib.api.Models",
184        "OutgoingSyncDeleteAction": "authentik.lib.sync.outgoing.models.OutgoingSyncDeleteAction",
185        "PKCEMethodEnum": "authentik.sources.oauth.models.PKCEMethod",
186        "PolicyEngineMode": "authentik.policies.models.PolicyEngineMode",
187        "PromptTypeEnum": "authentik.stages.prompt.models.FieldTypes",
188        "ProxyMode": "authentik.providers.proxy.models.ProxyMode",
189        "SAMLBindingsEnum": "authentik.providers.saml.models.SAMLBindings",
190        "SAMLLogoutMethods": "authentik.providers.saml.models.SAMLLogoutMethods",
191        "SAMLNameIDPolicyEnum": "authentik.sources.saml.models.SAMLNameIDPolicy",
192        "SCIMAuthenticationModeEnum": "authentik.providers.scim.models.SCIMAuthenticationMode",
193        "StageModeEnum": "authentik.endpoints.models.StageMode",
194        "TaskAggregatedStatusEnum": "authentik.tasks.models.TaskStatus",
195        "TaskStatusEnum": "django_dramatiq_postgres.models.TaskState",
196        "TransportModeEnum": "authentik.events.models.TransportMode",
197        "UserTypeEnum": "authentik.core.models.UserTypes",
198        "UserVerificationEnum": "authentik.stages.authenticator_webauthn.models.UserVerification",
199        "WebAuthnHintEnum": "authentik.stages.authenticator_webauthn.models.WebAuthnHint",
200    },
201    "ENUM_ADD_EXPLICIT_BLANK_NULL_CHOICE": False,
202    "ENUM_GENERATE_CHOICE_DESCRIPTION": False,
203    "PREPROCESSING_HOOKS": [
204        "authentik.api.v3.schema.cleanup.preprocess_schema_exclude_non_api",
205    ],
206    "POSTPROCESSING_HOOKS": [
207        "authentik.api.v3.schema.response.postprocess_schema_register",
208        "authentik.api.v3.schema.response.postprocess_schema_responses",
209        "authentik.api.v3.schema.query.postprocess_schema_query_params",
210        "authentik.api.v3.schema.cleanup.postprocess_schema_remove_unused",
211        "authentik.api.v3.schema.enum.postprocess_schema_enums",
212    ],
213}
214
215REST_FRAMEWORK = {
216    "DEFAULT_PAGINATION_CLASS": "authentik.api.pagination.Pagination",
217    "DEFAULT_FILTER_BACKENDS": [
218        "authentik.rbac.filters.ObjectFilter",
219        "django_filters.rest_framework.DjangoFilterBackend",
220        "rest_framework.filters.OrderingFilter",
221        "rest_framework.filters.SearchFilter",
222    ],
223    "DEFAULT_PERMISSION_CLASSES": ("authentik.rbac.permissions.ObjectPermissions",),
224    "DEFAULT_AUTHENTICATION_CLASSES": (
225        "authentik.api.authentication.TokenAuthentication",
226        "rest_framework.authentication.SessionAuthentication",
227    ),
228    "DEFAULT_RENDERER_CLASSES": [
229        "drf_orjson_renderer.renderers.ORJSONRenderer",
230    ],
231    "ORJSON_RENDERER_OPTIONS": [
232        orjson.OPT_NON_STR_KEYS,
233        orjson.OPT_UTC_Z,
234    ],
235    "DEFAULT_PARSER_CLASSES": [
236        "drf_orjson_renderer.parsers.ORJSONParser",
237    ],
238    "DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
239    "TEST_REQUEST_DEFAULT_FORMAT": "json",
240    "DEFAULT_THROTTLE_CLASSES": ["rest_framework.throttling.AnonRateThrottle"],
241    "DEFAULT_THROTTLE_RATES": {
242        "anon": CONFIG.get("throttle.default"),
243    },
244}
245
246
247CACHES = {
248    "default": {
249        "BACKEND": "django_postgres_cache.backend.DatabaseCache",
250        "KEY_FUNCTION": "django_tenants.cache.make_key",
251        "REVERSE_KEY_FUNCTION": "django_tenants.cache.reverse_key",
252    }
253}
254SESSION_ENGINE = "authentik.core.sessions"
255# Configured via custom SessionMiddleware
256# SESSION_COOKIE_SAMESITE = "None"
257# SESSION_COOKIE_SECURE = True
258SESSION_COOKIE_AGE = timedelta_from_string(
259    CONFIG.get("sessions.unauthenticated_age", "days=1")
260).total_seconds()
261SESSION_EXPIRE_AT_BROWSER_CLOSE = True
262
263MESSAGE_STORAGE = "authentik.root.ws.storage.ChannelsStorage"
264
265MIDDLEWARE_FIRST = [
266    "django_prometheus.middleware.PrometheusBeforeMiddleware",
267]
268MIDDLEWARE = [
269    "authentik.tenants.middleware.DefaultTenantMiddleware",
270    "authentik.root.middleware.LoggingMiddleware",
271    "authentik.root.middleware.ClientIPMiddleware",
272    "authentik.stages.user_login.middleware.BoundSessionMiddleware",
273    "django.middleware.locale.LocaleMiddleware",
274    "authentik.core.middleware.AuthenticationMiddleware",
275    "authentik.core.middleware.RequestIDMiddleware",
276    "authentik.brands.middleware.BrandMiddleware",
277    "authentik.events.middleware.AuditMiddleware",
278    "django.middleware.security.SecurityMiddleware",
279    "django.middleware.common.CommonMiddleware",
280    "authentik.root.middleware.CsrfViewMiddleware",
281    "django.contrib.messages.middleware.MessageMiddleware",
282    "django.middleware.clickjacking.XFrameOptionsMiddleware",
283    "authentik.core.middleware.ImpersonateMiddleware",
284    "authentik.rbac.middleware.InitialPermissionsMiddleware",
285]
286MIDDLEWARE_LAST = [
287    "django_prometheus.middleware.PrometheusAfterMiddleware",
288]
289
290ROOT_URLCONF = "authentik.root.urls"
291
292TEMPLATES = [
293    {
294        "BACKEND": "django.template.backends.django.DjangoTemplates",
295        "DIRS": [CONFIG.get("email.template_dir")],
296        "APP_DIRS": True,
297        "OPTIONS": {
298            "context_processors": [
299                "django.template.context_processors.debug",
300                "django.template.context_processors.request",
301                "django.contrib.auth.context_processors.auth",
302                "django.contrib.messages.context_processors.messages",
303                "authentik.brands.utils.context_processor",
304            ],
305        },
306    },
307]
308
309ASGI_APPLICATION = "authentik.root.asgi.application"
310
311
312# Database
313# https://docs.djangoproject.com/en/2.1/ref/settings/#databases
314
315# Custom overrides for database backends
316# The tree looks like this:
317# psqlextra backend
318#   -> authentik custom backend
319#     -> django_tenants backend
320#       -> django_prometheus backend
321#         -> django built-in backend
322ORIGINAL_BACKEND = "django_prometheus.db.backends.postgresql"
323POSTGRES_EXTRA_DB_BACKEND_BASE = "authentik.root.db"
324DATABASES = django_db_config()
325
326DATABASE_ROUTERS = (
327    "authentik.tenants.db.FailoverRouter",
328    "django_tenants.routers.TenantSyncRouter",
329)
330
331# We don't use HStore
332POSTGRES_EXTRA_AUTO_EXTENSION_SET_UP = False
333
334CHANNEL_LAYERS = {
335    "default": {
336        "BACKEND": "django_channels_postgres.layer.PostgresChannelLayer",
337    },
338}
339
340# Email
341# These values should never actually be used, emails are only sent from email stages, which
342# loads the config directly from CONFIG
343# See authentik/stages/email/models.py, line 105
344EMAIL_HOST = CONFIG.get("email.host")
345EMAIL_PORT = CONFIG.get_int("email.port")
346EMAIL_HOST_USER = CONFIG.get("email.username")
347EMAIL_HOST_PASSWORD = CONFIG.get("email.password")
348EMAIL_USE_TLS = CONFIG.get_bool("email.use_tls", False)
349EMAIL_USE_SSL = CONFIG.get_bool("email.use_ssl", False)
350EMAIL_TIMEOUT = CONFIG.get_int("email.timeout")
351DEFAULT_FROM_EMAIL = CONFIG.get("email.from")
352SERVER_EMAIL = DEFAULT_FROM_EMAIL
353EMAIL_SUBJECT_PREFIX = "[authentik] "
354
355# Password validation
356# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators
357
358AUTH_PASSWORD_VALIDATORS = [
359    {
360        "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
361    },
362    {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"},
363    {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"},
364    {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"},
365]
366
367
368# Internationalization
369# https://docs.djangoproject.com/en/2.1/topics/i18n/
370
371LANGUAGE_CODE = "en-us"
372
373TIME_ZONE = "UTC"
374
375USE_I18N = True
376
377USE_TZ = True
378
379LOCALE_PATHS = ["./locale"]
380
381
382# Tests
383
384TEST = False
385TEST_RUNNER = "authentik.root.test_runner.PytestTestRunner"
386
387
388# Dramatiq
389
390DRAMATIQ = {
391    "broker_class": "authentik.tasks.broker.Broker",
392    "channel_prefix": "authentik",
393    "task_model": "authentik.tasks.models.Task",
394    "task_purge_interval": timedelta_from_string(
395        CONFIG.get("worker.task_purge_interval")
396    ).total_seconds(),
397    "task_expiration": timedelta_from_string(CONFIG.get("worker.task_expiration")).total_seconds(),
398    "autodiscovery": {
399        "enabled": True,
400        "setup_module": "authentik.tasks.setup",
401        "apps_prefix": "authentik",
402    },
403    "worker": {
404        "processes": CONFIG.get_int("worker.processes", 2),
405        "threads": CONFIG.get_int("worker.threads", 1),
406        "consumer_listen_timeout": timedelta_from_string(
407            CONFIG.get("worker.consumer_listen_timeout")
408        ).total_seconds(),
409        "watch_folder": BASE_DIR / "authentik",
410    },
411    "scheduler_class": "authentik.tasks.schedules.scheduler.Scheduler",
412    "schedule_model": "authentik.tasks.schedules.models.Schedule",
413    "scheduler_interval": timedelta_from_string(
414        CONFIG.get("worker.scheduler_interval")
415    ).total_seconds(),
416    "middlewares": (
417        ("django_dramatiq_postgres.middleware.FullyQualifiedActorName", {}),
418        ("django_dramatiq_postgres.middleware.DbConnectionMiddleware", {}),
419        ("django_dramatiq_postgres.middleware.TaskStateBeforeMiddleware", {}),
420        ("dramatiq.middleware.age_limit.AgeLimit", {}),
421        (
422            "dramatiq.middleware.time_limit.TimeLimit",
423            {
424                "time_limit": timedelta_from_string(
425                    CONFIG.get("worker.task_default_time_limit")
426                ).total_seconds()
427                * 1000
428            },
429        ),
430        ("dramatiq.middleware.shutdown.ShutdownNotifications", {}),
431        ("dramatiq.middleware.callbacks.Callbacks", {}),
432        ("dramatiq.middleware.pipelines.Pipelines", {}),
433        (
434            "dramatiq.middleware.retries.Retries",
435            {
436                "max_retries": CONFIG.get_int("worker.task_max_retries") if not TEST else 0,
437                "max_backoff": 60 * 60 * 1000,  # 1 hour
438            },
439        ),
440        ("dramatiq.results.middleware.Results", {"store_results": True}),
441        ("authentik.tasks.middleware.StartupSignalsMiddleware", {}),
442        ("authentik.tasks.middleware.CurrentTask", {}),
443        ("authentik.tasks.middleware.TenantMiddleware", {}),
444        ("authentik.tasks.middleware.ModelDataMiddleware", {}),
445        ("authentik.tasks.middleware.TaskLogMiddleware", {}),
446        ("authentik.tasks.middleware.LoggingMiddleware", {}),
447        ("authentik.tasks.middleware.DescriptionMiddleware", {}),
448        ("authentik.tasks.middleware.WorkerHealthcheckMiddleware", {}),
449        ("authentik.tasks.middleware.WorkerStatusMiddleware", {}),
450        (
451            "authentik.tasks.middleware.MetricsMiddleware",
452            {
453                "prefix": "authentik",
454            },
455        ),
456        ("django_dramatiq_postgres.middleware.TaskStateAfterMiddleware", {}),
457    ),
458    "test": TEST,
459}
460
461
462# Sentry integration
463
464env = get_env()
465_ERROR_REPORTING = CONFIG.get_bool("error_reporting.enabled", False)
466if _ERROR_REPORTING:
467    sentry_env = CONFIG.get("error_reporting.environment", "customer")
468    sentry_init(spotlight=DEBUG)
469    set_tag("authentik.uuid", sha512(str(SECRET_KEY).encode("ascii")).hexdigest()[:16])
470
471
472# Static files (CSS, JavaScript, Images)
473# https://docs.djangoproject.com/en/2.1/howto/static-files/
474
475STATICFILES_DIRS = [BASE_DIR / Path("web")]
476STATIC_URL = CONFIG.get("web.path", "/") + "static/"
477
478STORAGES = {
479    "staticfiles": {
480        "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
481    },
482}
483
484# Django 5.2.8 and CVE-2025-64458 added a strong enforcement of 2048 characters
485# as the maximum for a URL to redirect to, mostly for running on Windows.
486# However, our URLs can easily exceed that with OAuth/SAML Query parameters or hash values.
487# 8192 should cover most cases.
488utils_http.MAX_URL_LENGTH = utils_http.MAX_URL_LENGTH * 4
489
490structlog_configure()
491LOGGING = get_logger_config()
492
493
494_DISALLOWED_ITEMS = [
495    "SHARED_APPS",
496    "TENANT_APPS",
497    "INSTALLED_APPS",
498    "MIDDLEWARE_FIRST",
499    "MIDDLEWARE",
500    "MIDDLEWARE_LAST",
501    "AUTHENTICATION_BACKENDS",
502    "SPECTACULAR_SETTINGS",
503    "REST_FRAMEWORK",
504]
505
506SILENCED_SYSTEM_CHECKS = [
507    # We use our own subclass of django.middleware.csrf.CsrfViewMiddleware
508    "security.W003",
509    # We don't set SESSION_COOKIE_SECURE since we use a custom SessionMiddleware subclass
510    "security.W010",
511    # HSTS: This is configured in reverse proxies/the go proxy, not in django
512    "security.W004",
513    # https redirect: This is configured in reverse proxies/the go proxy, not in django
514    "security.W008",
515]
516
517
518def subtract_list(a: list, b: list) -> list:
519    return [item for item in a if item not in b]
520
521
522def _filter_and_update(apps: list[str]) -> None:
523    for _app in set(apps):
524        if not _app.startswith("authentik"):
525            continue
526        _update_settings(f"{_app}.settings")
527
528
529def _update_settings(app_path: str) -> None:
530    try:
531        settings_module = importlib.import_module(app_path)
532        CONFIG.log("debug", "Loaded app settings", path=app_path)
533
534        new_shared_apps = subtract_list(getattr(settings_module, "SHARED_APPS", []), SHARED_APPS)
535        new_tenant_apps = subtract_list(getattr(settings_module, "TENANT_APPS", []), TENANT_APPS)
536        SHARED_APPS.extend(new_shared_apps)
537        TENANT_APPS.extend(new_tenant_apps)
538        _filter_and_update(new_shared_apps + new_tenant_apps)
539
540        MIDDLEWARE_FIRST.extend(getattr(settings_module, "MIDDLEWARE_FIRST", []))
541        MIDDLEWARE.extend(getattr(settings_module, "MIDDLEWARE", []))
542
543        AUTHENTICATION_BACKENDS.extend(getattr(settings_module, "AUTHENTICATION_BACKENDS", []))
544        SPECTACULAR_SETTINGS.update(getattr(settings_module, "SPECTACULAR_SETTINGS", {}))
545        REST_FRAMEWORK.update(getattr(settings_module, "REST_FRAMEWORK", {}))
546
547        for _attr in dir(settings_module):
548            if not _attr.startswith("__") and _attr not in _DISALLOWED_ITEMS:
549                globals()[_attr] = getattr(settings_module, _attr)
550    except ImportError:
551        pass
552
553
554# Attempt to load enterprise app, if available
555try:
556    importlib.import_module("authentik.enterprise.apps")
557    CONFIG.log("info", "Enabled authentik enterprise")
558    TENANT_APPS.insert(TENANT_APPS.index("authentik.events"), "authentik.enterprise")
559except ImportError:
560    pass
561
562
563if DEBUG:
564    REST_FRAMEWORK["DEFAULT_RENDERER_CLASSES"].append(
565        "rest_framework.renderers.BrowsableAPIRenderer"
566    )
567    SHARED_APPS.insert(SHARED_APPS.index("django.contrib.staticfiles"), "daphne")
568    enable_debug_trace(True)
569
570
571CONFIG.log("info", "Booting authentik", version=authentik_version())
572
573# Load subapps's settings
574_filter_and_update(SHARED_APPS + TENANT_APPS)
575_update_settings("data.user_settings")
576
577MIDDLEWARE = list(OrderedDict.fromkeys(MIDDLEWARE_FIRST + MIDDLEWARE + MIDDLEWARE_LAST))
578SHARED_APPS = list(OrderedDict.fromkeys(SHARED_APPS + TENANT_APPS))
579INSTALLED_APPS = list(OrderedDict.fromkeys(SHARED_APPS + TENANT_APPS))
BASE_DIR = PosixPath('/home/runner/work/authentik/authentik')
DEBUG = False
SECRET_KEY = 'bHyobnU2BszZqeFjdpSDwcx1dPSIQ0LyFuRF1YZF'
INTERNAL_IPS = ['127.0.0.1']
ALLOWED_HOSTS = ['*']
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_CROSS_ORIGIN_OPENER_POLICY = None
LOGIN_URL = 'authentik_flows:default-authentication'
AUTH_USER_MODEL = 'authentik_core.User'
CSRF_HEADER_NAME = 'HTTP_X_AUTHENTIK_CSRF'
APPEND_SLASH = False
AUTHENTICATION_BACKENDS = ['authentik.core.auth.InbuiltBackend', 'authentik.core.auth.TokenBackend', 'authentik.sources.ldap.auth.LDAPBackend', 'guardian.backends.ObjectPermissionBackend']
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
SHARED_APPS = ['authentik.commands', 'django_tenants', 'authentik.tenants', 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.humanize', 'django.contrib.postgres', 'psqlextra', 'rest_framework', 'django_filters', 'drf_spectacular', 'django_prometheus', 'django_countries', 'pgactivity', 'pglock', 'channels', 'django_channels_postgres', 'django_dramatiq_postgres', 'authentik.tasks', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'pgtrigger', 'django_postgres_cache', 'authentik.admin', 'authentik.api', 'authentik.core', 'authentik.crypto', 'authentik.endpoints', 'authentik.endpoints.connectors.agent', 'authentik.enterprise', 'authentik.events', 'authentik.admin.files', 'authentik.flows', 'authentik.outposts', 'authentik.policies.dummy', 'authentik.policies.event_matcher', 'authentik.policies.expiry', 'authentik.policies.expression', 'authentik.policies.geoip', 'authentik.policies.password', 'authentik.policies.reputation', 'authentik.policies', 'authentik.providers.ldap', 'authentik.providers.oauth2', 'authentik.providers.proxy', 'authentik.providers.rac', 'authentik.providers.radius', 'authentik.providers.saml', 'authentik.providers.scim', 'authentik.rbac', 'authentik.recovery', 'authentik.sources.kerberos', 'authentik.sources.ldap', 'authentik.sources.oauth', 'authentik.sources.plex', 'authentik.sources.saml', 'authentik.sources.scim', 'authentik.sources.telegram', 'authentik.stages.authenticator', 'authentik.stages.authenticator_duo', 'authentik.stages.authenticator_email', 'authentik.stages.authenticator_sms', 'authentik.stages.authenticator_static', 'authentik.stages.authenticator_totp', 'authentik.stages.authenticator_validate', 'authentik.stages.authenticator_webauthn', 'authentik.stages.captcha', 'authentik.stages.consent', 'authentik.stages.deny', 'authentik.stages.dummy', 'authentik.stages.email', 'authentik.stages.identification', 'authentik.stages.invitation', 'authentik.stages.password', 'authentik.stages.prompt', 'authentik.stages.redirect', 'authentik.stages.user_delete', 'authentik.stages.user_login', 'authentik.stages.user_logout', 'authentik.stages.user_write', 'authentik.tasks.schedules', 'authentik.brands', 'authentik.blueprints', 'guardian', 'authentik.enterprise.audit', 'authentik.enterprise.endpoints.connectors.agent', 'authentik.enterprise.endpoints.connectors.fleet', 'authentik.enterprise.endpoints.connectors.google_chrome', 'authentik.enterprise.lifecycle', 'authentik.enterprise.policies.unique_password', 'authentik.enterprise.providers.google_workspace', 'authentik.enterprise.providers.microsoft_entra', 'authentik.enterprise.providers.radius', 'authentik.enterprise.providers.scim', 'authentik.enterprise.providers.ssf', 'authentik.enterprise.providers.ws_federation', 'authentik.enterprise.reports', 'authentik.enterprise.search', 'authentik.enterprise.stages.authenticator_endpoint_gdtc', 'authentik.enterprise.stages.mtls', 'authentik.enterprise.stages.source']
TENANT_APPS = ['django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'pgtrigger', 'django_postgres_cache', 'authentik.admin', 'authentik.api', 'authentik.core', 'authentik.crypto', 'authentik.endpoints', 'authentik.endpoints.connectors.agent', 'authentik.enterprise', 'authentik.events', 'authentik.admin.files', 'authentik.flows', 'authentik.outposts', 'authentik.policies.dummy', 'authentik.policies.event_matcher', 'authentik.policies.expiry', 'authentik.policies.expression', 'authentik.policies.geoip', 'authentik.policies.password', 'authentik.policies.reputation', 'authentik.policies', 'authentik.providers.ldap', 'authentik.providers.oauth2', 'authentik.providers.proxy', 'authentik.providers.rac', 'authentik.providers.radius', 'authentik.providers.saml', 'authentik.providers.scim', 'authentik.rbac', 'authentik.recovery', 'authentik.sources.kerberos', 'authentik.sources.ldap', 'authentik.sources.oauth', 'authentik.sources.plex', 'authentik.sources.saml', 'authentik.sources.scim', 'authentik.sources.telegram', 'authentik.stages.authenticator', 'authentik.stages.authenticator_duo', 'authentik.stages.authenticator_email', 'authentik.stages.authenticator_sms', 'authentik.stages.authenticator_static', 'authentik.stages.authenticator_totp', 'authentik.stages.authenticator_validate', 'authentik.stages.authenticator_webauthn', 'authentik.stages.captcha', 'authentik.stages.consent', 'authentik.stages.deny', 'authentik.stages.dummy', 'authentik.stages.email', 'authentik.stages.identification', 'authentik.stages.invitation', 'authentik.stages.password', 'authentik.stages.prompt', 'authentik.stages.redirect', 'authentik.stages.user_delete', 'authentik.stages.user_login', 'authentik.stages.user_logout', 'authentik.stages.user_write', 'authentik.tasks.schedules', 'authentik.brands', 'authentik.blueprints', 'guardian', 'authentik.enterprise.audit', 'authentik.enterprise.endpoints.connectors.agent', 'authentik.enterprise.endpoints.connectors.fleet', 'authentik.enterprise.endpoints.connectors.google_chrome', 'authentik.enterprise.lifecycle', 'authentik.enterprise.policies.unique_password', 'authentik.enterprise.providers.google_workspace', 'authentik.enterprise.providers.microsoft_entra', 'authentik.enterprise.providers.radius', 'authentik.enterprise.providers.scim', 'authentik.enterprise.providers.ssf', 'authentik.enterprise.providers.ws_federation', 'authentik.enterprise.reports', 'authentik.enterprise.search', 'authentik.enterprise.stages.authenticator_endpoint_gdtc', 'authentik.enterprise.stages.mtls', 'authentik.enterprise.stages.source']
TENANT_MODEL = 'authentik_tenants.Tenant'
TENANT_DOMAIN_MODEL = 'authentik_tenants.Domain'
TENANT_CREATION_FAKES_MIGRATIONS = True
TENANT_BASE_SCHEMA = 'template'
PUBLIC_SCHEMA_NAME = 'public'
GUARDIAN_GROUP_MODEL = 'authentik_core.Group'
GUARDIAN_ROLE_MODEL = 'authentik_rbac.Role'
SPECTACULAR_SETTINGS = {'TITLE': 'authentik', 'DESCRIPTION': 'Making authentication simple.', 'VERSION': '2026.5.0-rc1', 'COMPONENT_SPLIT_REQUEST': True, 'SCHEMA_PATH_PREFIX': '/api/v([0-9]+(beta)?)', 'SCHEMA_PATH_PREFIX_TRIM': True, 'SERVERS': [{'url': '/api/v3'}], 'CONTACT': {'email': 'hello@goauthentik.io'}, 'AUTHENTICATION_WHITELIST': ['authentik.api.authentication.TokenAuthentication'], 'LICENSE': {'name': 'MIT', 'url': 'https://github.com/goauthentik/authentik/blob/main/LICENSE'}, 'ENUM_NAME_OVERRIDES': {'AppEnum': 'authentik.lib.api.Apps', 'ConsentModeEnum': 'authentik.stages.consent.models.ConsentMode', 'CountryCodeEnum': 'django_countries.countries', 'DeviceClassesEnum': 'authentik.stages.authenticator_validate.models.DeviceClasses', 'DeviceFactsOSFamily': 'authentik.endpoints.facts.OSFamily', 'EventActions': 'authentik.events.models.EventAction', 'FlowDesignationEnum': 'authentik.flows.models.FlowDesignation', 'FlowLayoutEnum': 'authentik.flows.models.FlowLayout', 'LDAPAPIAccessMode': 'authentik.providers.ldap.models.APIAccessMode', 'ModelEnum': 'authentik.lib.api.Models', 'OutgoingSyncDeleteAction': 'authentik.lib.sync.outgoing.models.OutgoingSyncDeleteAction', 'PKCEMethodEnum': 'authentik.sources.oauth.models.PKCEMethod', 'PolicyEngineMode': 'authentik.policies.models.PolicyEngineMode', 'PromptTypeEnum': 'authentik.stages.prompt.models.FieldTypes', 'ProxyMode': 'authentik.providers.proxy.models.ProxyMode', 'SAMLBindingsEnum': 'authentik.providers.saml.models.SAMLBindings', 'SAMLLogoutMethods': 'authentik.providers.saml.models.SAMLLogoutMethods', 'SAMLNameIDPolicyEnum': 'authentik.sources.saml.models.SAMLNameIDPolicy', 'SCIMAuthenticationModeEnum': 'authentik.providers.scim.models.SCIMAuthenticationMode', 'StageModeEnum': 'authentik.endpoints.models.StageMode', 'TaskAggregatedStatusEnum': 'authentik.tasks.models.TaskStatus', 'TaskStatusEnum': 'django_dramatiq_postgres.models.TaskState', 'TransportModeEnum': 'authentik.events.models.TransportMode', 'UserTypeEnum': 'authentik.core.models.UserTypes', 'UserVerificationEnum': 'authentik.stages.authenticator_webauthn.models.UserVerification', 'WebAuthnHintEnum': 'authentik.stages.authenticator_webauthn.models.WebAuthnHint'}, 'ENUM_ADD_EXPLICIT_BLANK_NULL_CHOICE': False, 'ENUM_GENERATE_CHOICE_DESCRIPTION': False, 'PREPROCESSING_HOOKS': ['authentik.api.v3.schema.cleanup.preprocess_schema_exclude_non_api'], 'POSTPROCESSING_HOOKS': ['authentik.api.v3.schema.response.postprocess_schema_register', 'authentik.api.v3.schema.response.postprocess_schema_responses', 'authentik.api.v3.schema.query.postprocess_schema_query_params', 'authentik.api.v3.schema.cleanup.postprocess_schema_remove_unused', 'authentik.enterprise.search.schema.postprocess_schema_search_autocomplete', 'authentik.api.v3.schema.enum.postprocess_schema_enums']}
REST_FRAMEWORK = {'DEFAULT_PAGINATION_CLASS': 'authentik.enterprise.search.pagination.AutocompletePagination', 'DEFAULT_FILTER_BACKENDS': ['authentik.enterprise.search.ql.QLSearch', 'authentik.rbac.filters.ObjectFilter', 'django_filters.rest_framework.DjangoFilterBackend', 'rest_framework.filters.OrderingFilter'], 'DEFAULT_PERMISSION_CLASSES': ('authentik.rbac.permissions.ObjectPermissions',), 'DEFAULT_AUTHENTICATION_CLASSES': ('authentik.api.authentication.TokenAuthentication', 'rest_framework.authentication.SessionAuthentication'), 'DEFAULT_RENDERER_CLASSES': ['drf_orjson_renderer.renderers.ORJSONRenderer'], 'ORJSON_RENDERER_OPTIONS': [4, 128], 'DEFAULT_PARSER_CLASSES': ['drf_orjson_renderer.parsers.ORJSONParser'], 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema', 'TEST_REQUEST_DEFAULT_FORMAT': 'json', 'DEFAULT_THROTTLE_CLASSES': ['rest_framework.throttling.AnonRateThrottle'], 'DEFAULT_THROTTLE_RATES': {'anon': '1000/second'}}
CACHES = {'default': {'BACKEND': 'django_postgres_cache.backend.DatabaseCache', 'KEY_FUNCTION': 'django_tenants.cache.make_key', 'REVERSE_KEY_FUNCTION': 'django_tenants.cache.reverse_key'}}
SESSION_ENGINE = 'authentik.core.sessions'
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
MIDDLEWARE_FIRST = ['django_prometheus.middleware.PrometheusBeforeMiddleware']
MIDDLEWARE = ['django_prometheus.middleware.PrometheusBeforeMiddleware', 'authentik.tenants.middleware.DefaultTenantMiddleware', 'authentik.root.middleware.LoggingMiddleware', 'authentik.root.middleware.ClientIPMiddleware', 'authentik.stages.user_login.middleware.BoundSessionMiddleware', 'django.middleware.locale.LocaleMiddleware', 'authentik.core.middleware.AuthenticationMiddleware', 'authentik.core.middleware.RequestIDMiddleware', 'authentik.brands.middleware.BrandMiddleware', 'authentik.events.middleware.AuditMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.middleware.common.CommonMiddleware', 'authentik.root.middleware.CsrfViewMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'authentik.core.middleware.ImpersonateMiddleware', 'authentik.rbac.middleware.InitialPermissionsMiddleware', 'authentik.enterprise.middleware.EnterpriseMiddleware', 'django_prometheus.middleware.PrometheusAfterMiddleware']
MIDDLEWARE_LAST = ['django_prometheus.middleware.PrometheusAfterMiddleware']
ROOT_URLCONF = 'authentik.root.urls'
TEMPLATES = [{'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': ['/templates'], 'APP_DIRS': True, 'OPTIONS': {'context_processors': ['django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', 'authentik.brands.utils.context_processor']}}]
ASGI_APPLICATION = 'authentik.root.asgi.application'
ORIGINAL_BACKEND = 'django_prometheus.db.backends.postgresql'
POSTGRES_EXTRA_DB_BACKEND_BASE = 'authentik.root.db'
DATABASES = {'default': {'ENGINE': 'psqlextra.backend', 'HOST': 'localhost', 'NAME': 'authentik', 'USER': 'authentik', 'PASSWORD': 'EK-5jnKfjrGRm<77', 'PORT': 5432, 'OPTIONS': {'sslmode': 'disable', 'sslrootcert': None, 'sslcert': None, 'sslkey': None, 'pool': False}, 'CONN_MAX_AGE': 0, 'CONN_HEALTH_CHECKS': False, 'DISABLE_SERVER_SIDE_CURSORS': False, 'TEST': {'NAME': 'test_authentik', 'CHARSET': None, 'COLLATION': None, 'MIGRATE': True, 'MIRROR': None}, 'ATOMIC_REQUESTS': False, 'AUTOCOMMIT': True, 'TIME_ZONE': None, 'SCHEMA': 'public'}}
DATABASE_ROUTERS = ('authentik.tenants.db.FailoverRouter', 'django_tenants.routers.TenantSyncRouter')
POSTGRES_EXTRA_AUTO_EXTENSION_SET_UP = False
CHANNEL_LAYERS = {'default': {'BACKEND': 'django_channels_postgres.layer.PostgresChannelLayer'}}
EMAIL_HOST = 'localhost'
EMAIL_PORT = 25
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
EMAIL_USE_TLS = False
EMAIL_USE_SSL = False
EMAIL_TIMEOUT = 10
DEFAULT_FROM_EMAIL = 'authentik@localhost'
SERVER_EMAIL = 'authentik@localhost'
EMAIL_SUBJECT_PREFIX = '[authentik] '
AUTH_PASSWORD_VALIDATORS = [{'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator'}, {'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator'}, {'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator'}, {'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'}]
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
LOCALE_PATHS = ['./locale']
TEST = False
DRAMATIQ = {'broker_class': 'authentik.tasks.broker.Broker', 'channel_prefix': 'authentik', 'task_model': 'authentik.tasks.models.Task', 'task_purge_interval': 86400.0, 'task_expiration': 2592000.0, 'autodiscovery': {'enabled': True, 'setup_module': 'authentik.tasks.setup', 'apps_prefix': 'authentik'}, 'worker': {'processes': 1, 'threads': 2, 'consumer_listen_timeout': 30.0, 'watch_folder': PosixPath('/home/runner/work/authentik/authentik/authentik')}, 'scheduler_class': 'authentik.tasks.schedules.scheduler.Scheduler', 'schedule_model': 'authentik.tasks.schedules.models.Schedule', 'scheduler_interval': 60.0, 'middlewares': (('django_dramatiq_postgres.middleware.FullyQualifiedActorName', {}), ('django_dramatiq_postgres.middleware.DbConnectionMiddleware', {}), ('django_dramatiq_postgres.middleware.TaskStateBeforeMiddleware', {}), ('dramatiq.middleware.age_limit.AgeLimit', {}), ('dramatiq.middleware.time_limit.TimeLimit', {'time_limit': 600000.0}), ('dramatiq.middleware.shutdown.ShutdownNotifications', {}), ('dramatiq.middleware.callbacks.Callbacks', {}), ('dramatiq.middleware.pipelines.Pipelines', {}), ('dramatiq.middleware.retries.Retries', {'max_retries': 5, 'max_backoff': 3600000}), ('dramatiq.results.middleware.Results', {'store_results': True}), ('authentik.tasks.middleware.StartupSignalsMiddleware', {}), ('authentik.tasks.middleware.CurrentTask', {}), ('authentik.tasks.middleware.TenantMiddleware', {}), ('authentik.tasks.middleware.ModelDataMiddleware', {}), ('authentik.tasks.middleware.TaskLogMiddleware', {}), ('authentik.tasks.middleware.LoggingMiddleware', {}), ('authentik.tasks.middleware.DescriptionMiddleware', {}), ('authentik.tasks.middleware.WorkerHealthcheckMiddleware', {}), ('authentik.tasks.middleware.WorkerStatusMiddleware', {}), ('authentik.tasks.middleware.MetricsMiddleware', {'prefix': 'authentik'}), ('django_dramatiq_postgres.middleware.TaskStateAfterMiddleware', {})), 'test': False}
env = 'ci'
STATICFILES_DIRS = [PosixPath('/home/runner/work/authentik/authentik/web')]
STATIC_URL = '/static/'
STORAGES = {'staticfiles': {'BACKEND': 'django.contrib.staticfiles.storage.StaticFilesStorage'}}
LOGGING = {'version': 1, 'disable_existing_loggers': False, 'formatters': {'json': {'()': <class 'structlog.stdlib.ProcessorFormatter'>, 'processor': <structlog.processors.JSONRenderer object>, 'foreign_pre_chain': [<function add_log_level>, <function add_logger_name>, <structlog.processors.TimeStamper object>, <structlog.processors.StackInfoRenderer object>, <structlog.processors.ExceptionRenderer object>]}, 'console': {'()': <class 'structlog.stdlib.ProcessorFormatter'>, 'processor': <structlog.dev.ConsoleRenderer object>, 'foreign_pre_chain': [<function add_log_level>, <function add_logger_name>, <structlog.processors.TimeStamper object>, <structlog.processors.StackInfoRenderer object>]}}, 'handlers': {'console': {'level': 'DEBUG', 'class': 'logging.StreamHandler', 'formatter': 'json'}}, 'loggers': {'': {'handlers': ['console'], 'level': 'DEBUG', 'propagate': False}, 'authentik': {'handlers': ['console'], 'level': 'DEBUG', 'propagate': False}, 'django': {'handlers': ['console'], 'level': 'WARNING', 'propagate': False}, 'django.request': {'handlers': ['console'], 'level': 'ERROR', 'propagate': False}, 'selenium': {'handlers': ['console'], 'level': 'WARNING', 'propagate': False}, 'docker': {'handlers': ['console'], 'level': 'WARNING', 'propagate': False}, 'urllib3': {'handlers': ['console'], 'level': 'WARNING', 'propagate': False}, 'websockets': {'handlers': ['console'], 'level': 'WARNING', 'propagate': False}, 'daphne': {'handlers': ['console'], 'level': 'WARNING', 'propagate': False}, 'kubernetes': {'handlers': ['console'], 'level': 'INFO', 'propagate': False}, 'asyncio': {'handlers': ['console'], 'level': 'WARNING', 'propagate': False}, 'fsevents': {'handlers': ['console'], 'level': 'WARNING', 'propagate': False}, 'uvicorn': {'handlers': ['console'], 'level': 'WARNING', 'propagate': False}, 'gunicorn': {'handlers': ['console'], 'level': 'INFO', 'propagate': False}, 'requests_mock': {'handlers': ['console'], 'level': 'WARNING', 'propagate': False}, 'hpack': {'handlers': ['console'], 'level': 'WARNING', 'propagate': False}, 'httpx': {'handlers': ['console'], 'level': 'WARNING', 'propagate': False}, 'azure': {'handlers': ['console'], 'level': 'WARNING', 'propagate': False}, 'httpcore': {'handlers': ['console'], 'level': 'WARNING', 'propagate': False}}}
SILENCED_SYSTEM_CHECKS = ['security.W003', 'security.W010', 'security.W004', 'security.W008']
def subtract_list(a: list, b: list) -> list:
519def subtract_list(a: list, b: list) -> list:
520    return [item for item in a if item not in b]
INSTALLED_APPS = ['authentik.commands', 'django_tenants', 'authentik.tenants', 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.humanize', 'django.contrib.postgres', 'psqlextra', 'rest_framework', 'django_filters', 'drf_spectacular', 'django_prometheus', 'django_countries', 'pgactivity', 'pglock', 'channels', 'django_channels_postgres', 'django_dramatiq_postgres', 'authentik.tasks', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'pgtrigger', 'django_postgres_cache', 'authentik.admin', 'authentik.api', 'authentik.core', 'authentik.crypto', 'authentik.endpoints', 'authentik.endpoints.connectors.agent', 'authentik.enterprise', 'authentik.events', 'authentik.admin.files', 'authentik.flows', 'authentik.outposts', 'authentik.policies.dummy', 'authentik.policies.event_matcher', 'authentik.policies.expiry', 'authentik.policies.expression', 'authentik.policies.geoip', 'authentik.policies.password', 'authentik.policies.reputation', 'authentik.policies', 'authentik.providers.ldap', 'authentik.providers.oauth2', 'authentik.providers.proxy', 'authentik.providers.rac', 'authentik.providers.radius', 'authentik.providers.saml', 'authentik.providers.scim', 'authentik.rbac', 'authentik.recovery', 'authentik.sources.kerberos', 'authentik.sources.ldap', 'authentik.sources.oauth', 'authentik.sources.plex', 'authentik.sources.saml', 'authentik.sources.scim', 'authentik.sources.telegram', 'authentik.stages.authenticator', 'authentik.stages.authenticator_duo', 'authentik.stages.authenticator_email', 'authentik.stages.authenticator_sms', 'authentik.stages.authenticator_static', 'authentik.stages.authenticator_totp', 'authentik.stages.authenticator_validate', 'authentik.stages.authenticator_webauthn', 'authentik.stages.captcha', 'authentik.stages.consent', 'authentik.stages.deny', 'authentik.stages.dummy', 'authentik.stages.email', 'authentik.stages.identification', 'authentik.stages.invitation', 'authentik.stages.password', 'authentik.stages.prompt', 'authentik.stages.redirect', 'authentik.stages.user_delete', 'authentik.stages.user_login', 'authentik.stages.user_logout', 'authentik.stages.user_write', 'authentik.tasks.schedules', 'authentik.brands', 'authentik.blueprints', 'guardian', 'authentik.enterprise.audit', 'authentik.enterprise.endpoints.connectors.agent', 'authentik.enterprise.endpoints.connectors.fleet', 'authentik.enterprise.endpoints.connectors.google_chrome', 'authentik.enterprise.lifecycle', 'authentik.enterprise.policies.unique_password', 'authentik.enterprise.providers.google_workspace', 'authentik.enterprise.providers.microsoft_entra', 'authentik.enterprise.providers.radius', 'authentik.enterprise.providers.scim', 'authentik.enterprise.providers.ssf', 'authentik.enterprise.providers.ws_federation', 'authentik.enterprise.reports', 'authentik.enterprise.search', 'authentik.enterprise.stages.authenticator_endpoint_gdtc', 'authentik.enterprise.stages.mtls', 'authentik.enterprise.stages.source']