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 "AuthenticationEnum": "authentik.flows.models.FlowAuthenticationRequirement", 176 "ConsentModeEnum": "authentik.stages.consent.models.ConsentMode", 177 "CountryCodeEnum": "django_countries.countries", 178 "DeviceClassesEnum": "authentik.stages.authenticator_validate.models.DeviceClasses", 179 "DeviceFactsOSFamily": "authentik.endpoints.facts.OSFamily", 180 "EventActions": "authentik.events.models.EventAction", 181 "FlowDesignationEnum": "authentik.flows.models.FlowDesignation", 182 "FlowLayoutEnum": "authentik.flows.models.FlowLayout", 183 "LDAPAPIAccessMode": "authentik.providers.ldap.models.APIAccessMode", 184 "ModelEnum": "authentik.lib.api.Models", 185 "OutgoingSyncDeleteAction": "authentik.lib.sync.outgoing.models.OutgoingSyncDeleteAction", 186 "PKCEMethodEnum": "authentik.sources.oauth.models.PKCEMethod", 187 "PolicyEngineMode": "authentik.policies.models.PolicyEngineMode", 188 "PromptTypeEnum": "authentik.stages.prompt.models.FieldTypes", 189 "ProxyMode": "authentik.providers.proxy.models.ProxyMode", 190 "RedirectURITypeEnum": "authentik.providers.oauth2.models.RedirectURIType", 191 "SAMLBindingsEnum": "authentik.providers.saml.models.SAMLBindings", 192 "SAMLLogoutMethods": "authentik.providers.saml.models.SAMLLogoutMethods", 193 "SAMLNameIDPolicyEnum": "authentik.sources.saml.models.SAMLNameIDPolicy", 194 "SCIMAuthenticationModeEnum": "authentik.providers.scim.models.SCIMAuthenticationMode", 195 "StageModeEnum": "authentik.endpoints.models.StageMode", 196 "TaskAggregatedStatusEnum": "authentik.tasks.models.TaskStatus", 197 "TaskStatusEnum": "django_dramatiq_postgres.models.TaskState", 198 "TransportModeEnum": "authentik.events.models.TransportMode", 199 "UserTypeEnum": "authentik.core.models.UserTypes", 200 "UserVerificationEnum": "authentik.stages.authenticator_webauthn.models.UserVerification", 201 "WebAuthnHintEnum": "authentik.stages.authenticator_webauthn.models.WebAuthnHint", 202 }, 203 "ENUM_ADD_EXPLICIT_BLANK_NULL_CHOICE": False, 204 "ENUM_GENERATE_CHOICE_DESCRIPTION": False, 205 "PREPROCESSING_HOOKS": [ 206 "authentik.api.v3.schema.cleanup.preprocess_schema_exclude_non_api", 207 ], 208 "POSTPROCESSING_HOOKS": [ 209 "authentik.api.v3.schema.response.postprocess_schema_register", 210 "authentik.api.v3.schema.response.postprocess_schema_responses", 211 "authentik.api.v3.schema.query.postprocess_schema_query_params", 212 "authentik.api.v3.schema.cleanup.postprocess_schema_remove_unused", 213 "authentik.api.v3.schema.search.postprocess_schema_search_autocomplete", 214 "authentik.api.v3.schema.enum.postprocess_schema_enums", 215 ], 216} 217 218REST_FRAMEWORK = { 219 "DEFAULT_PAGINATION_CLASS": "authentik.api.pagination.Pagination", 220 "DEFAULT_FILTER_BACKENDS": [ 221 "authentik.api.search.ql.QLSearch", 222 "authentik.rbac.filters.ObjectFilter", 223 "django_filters.rest_framework.DjangoFilterBackend", 224 "authentik.api.ordering.NullsAwareOrderingFilter", 225 ], 226 "DEFAULT_PERMISSION_CLASSES": ("authentik.rbac.permissions.ObjectPermissions",), 227 "DEFAULT_AUTHENTICATION_CLASSES": ( 228 "authentik.api.authentication.TokenAuthentication", 229 "rest_framework.authentication.SessionAuthentication", 230 ), 231 "DEFAULT_RENDERER_CLASSES": [ 232 "drf_orjson_renderer.renderers.ORJSONRenderer", 233 ], 234 "ORJSON_RENDERER_OPTIONS": [ 235 orjson.OPT_NON_STR_KEYS, 236 orjson.OPT_UTC_Z, 237 ], 238 "DEFAULT_PARSER_CLASSES": [ 239 "drf_orjson_renderer.parsers.ORJSONParser", 240 ], 241 "DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema", 242 "TEST_REQUEST_DEFAULT_FORMAT": "json", 243 "DEFAULT_THROTTLE_CLASSES": ["rest_framework.throttling.AnonRateThrottle"], 244 "DEFAULT_THROTTLE_RATES": { 245 "anon": CONFIG.get("throttle.default"), 246 }, 247} 248 249 250CACHES = { 251 "default": { 252 "BACKEND": "django_postgres_cache.backend.DatabaseCache", 253 "KEY_FUNCTION": "django_tenants.cache.make_key", 254 "REVERSE_KEY_FUNCTION": "django_tenants.cache.reverse_key", 255 } 256} 257SESSION_ENGINE = "authentik.core.sessions" 258# Configured via custom SessionMiddleware 259# SESSION_COOKIE_SAMESITE = "None" 260# SESSION_COOKIE_SECURE = True 261SESSION_COOKIE_AGE = timedelta_from_string( 262 CONFIG.get("sessions.unauthenticated_age", "days=1") 263).total_seconds() 264SESSION_EXPIRE_AT_BROWSER_CLOSE = True 265 266MESSAGE_STORAGE = "authentik.root.ws.storage.ChannelsStorage" 267 268MIDDLEWARE_FIRST = [ 269 "django_prometheus.middleware.PrometheusBeforeMiddleware", 270] 271MIDDLEWARE = [ 272 "authentik.tenants.middleware.DefaultTenantMiddleware", 273 "authentik.root.middleware.LoggingMiddleware", 274 "authentik.root.middleware.ClientIPMiddleware", 275 "authentik.stages.user_login.middleware.BoundSessionMiddleware", 276 "django.middleware.locale.LocaleMiddleware", 277 "authentik.core.middleware.AuthenticationMiddleware", 278 "authentik.core.middleware.RequestIDMiddleware", 279 "authentik.brands.middleware.BrandMiddleware", 280 "authentik.events.middleware.AuditMiddleware", 281 "django.middleware.security.SecurityMiddleware", 282 "django.middleware.common.CommonMiddleware", 283 "authentik.root.middleware.CsrfViewMiddleware", 284 "django.contrib.messages.middleware.MessageMiddleware", 285 "django.middleware.clickjacking.XFrameOptionsMiddleware", 286 "authentik.core.middleware.ImpersonateMiddleware", 287 "authentik.rbac.middleware.InitialPermissionsMiddleware", 288] 289MIDDLEWARE_LAST = [ 290 "django_prometheus.middleware.PrometheusAfterMiddleware", 291] 292 293ROOT_URLCONF = "authentik.root.urls" 294 295TEMPLATES = [ 296 { 297 "BACKEND": "django.template.backends.django.DjangoTemplates", 298 "DIRS": [CONFIG.get("email.template_dir")], 299 "APP_DIRS": True, 300 "OPTIONS": { 301 "context_processors": [ 302 "django.template.context_processors.debug", 303 "django.template.context_processors.request", 304 "django.contrib.auth.context_processors.auth", 305 "django.contrib.messages.context_processors.messages", 306 "authentik.brands.utils.context_processor", 307 ], 308 }, 309 }, 310] 311 312ASGI_APPLICATION = "authentik.root.asgi.application" 313 314 315# Database 316# https://docs.djangoproject.com/en/2.1/ref/settings/#databases 317 318# Custom overrides for database backends 319# The tree looks like this: 320# psqlextra backend 321# -> authentik custom backend 322# -> django_tenants backend 323# -> django_prometheus backend 324# -> django built-in backend 325ORIGINAL_BACKEND = "django_prometheus.db.backends.postgresql" 326POSTGRES_EXTRA_DB_BACKEND_BASE = "authentik.root.db" 327DATABASES = django_db_config() 328 329DATABASE_ROUTERS = ( 330 "authentik.tenants.db.FailoverRouter", 331 "django_tenants.routers.TenantSyncRouter", 332) 333 334# We don't use HStore 335POSTGRES_EXTRA_AUTO_EXTENSION_SET_UP = False 336 337CHANNEL_LAYERS = { 338 "default": { 339 "BACKEND": "django_channels_postgres.layer.PostgresChannelLayer", 340 }, 341} 342 343# Email 344# These values should never actually be used, emails are only sent from email stages, which 345# loads the config directly from CONFIG 346# See authentik/stages/email/models.py, line 105 347EMAIL_HOST = CONFIG.get("email.host") 348EMAIL_PORT = CONFIG.get_int("email.port") 349EMAIL_HOST_USER = CONFIG.get("email.username") 350EMAIL_HOST_PASSWORD = CONFIG.get("email.password") 351EMAIL_USE_TLS = CONFIG.get_bool("email.use_tls", False) 352EMAIL_USE_SSL = CONFIG.get_bool("email.use_ssl", False) 353EMAIL_TIMEOUT = CONFIG.get_int("email.timeout") 354DEFAULT_FROM_EMAIL = CONFIG.get("email.from") 355SERVER_EMAIL = DEFAULT_FROM_EMAIL 356EMAIL_SUBJECT_PREFIX = "[authentik] " 357 358# Password validation 359# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators 360 361AUTH_PASSWORD_VALIDATORS = [ 362 { 363 "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", 364 }, 365 {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"}, 366 {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"}, 367 {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"}, 368] 369 370 371# Internationalization 372# https://docs.djangoproject.com/en/2.1/topics/i18n/ 373 374LANGUAGE_CODE = "en-us" 375 376TIME_ZONE = "UTC" 377 378USE_I18N = True 379 380USE_TZ = True 381 382LOCALE_PATHS = ["./locale"] 383 384 385# Tests 386 387TEST = False 388TEST_RUNNER = "authentik.root.test_runner.PytestTestRunner" 389 390 391# Dramatiq 392 393DRAMATIQ = { 394 "broker_class": "authentik.tasks.broker.Broker", 395 "channel_prefix": "authentik", 396 "task_model": "authentik.tasks.models.Task", 397 "task_purge_interval": timedelta_from_string( 398 CONFIG.get("worker.task_purge_interval") 399 ).total_seconds(), 400 "task_expiration": timedelta_from_string(CONFIG.get("worker.task_expiration")).total_seconds(), 401 "autodiscovery": { 402 "enabled": True, 403 "setup_module": "authentik.tasks.setup", 404 "apps_prefix": "authentik", 405 }, 406 "worker": { 407 "processes": CONFIG.get_int("worker.processes", 2), 408 "threads": CONFIG.get_int("worker.threads", 1), 409 "consumer_listen_timeout": timedelta_from_string( 410 CONFIG.get("worker.consumer_listen_timeout") 411 ).total_seconds(), 412 "watch_folder": BASE_DIR / "authentik", 413 }, 414 "scheduler_class": "authentik.tasks.schedules.scheduler.Scheduler", 415 "schedule_model": "authentik.tasks.schedules.models.Schedule", 416 "scheduler_interval": timedelta_from_string( 417 CONFIG.get("worker.scheduler_interval") 418 ).total_seconds(), 419 "middlewares": ( 420 ("django_dramatiq_postgres.middleware.FullyQualifiedActorName", {}), 421 ("django_dramatiq_postgres.middleware.DbConnectionMiddleware", {}), 422 ("django_dramatiq_postgres.middleware.TaskStateBeforeMiddleware", {}), 423 ("dramatiq.middleware.age_limit.AgeLimit", {}), 424 ( 425 "dramatiq.middleware.time_limit.TimeLimit", 426 { 427 "time_limit": timedelta_from_string( 428 CONFIG.get("worker.task_default_time_limit") 429 ).total_seconds() 430 * 1000 431 }, 432 ), 433 ("dramatiq.middleware.shutdown.ShutdownNotifications", {}), 434 ("dramatiq.middleware.callbacks.Callbacks", {}), 435 ("dramatiq.middleware.pipelines.Pipelines", {}), 436 ( 437 "dramatiq.middleware.retries.Retries", 438 { 439 "max_retries": CONFIG.get_int("worker.task_max_retries") if not TEST else 0, 440 "max_backoff": 60 * 60 * 1000, # 1 hour 441 }, 442 ), 443 ("dramatiq.results.middleware.Results", {"store_results": True}), 444 ("authentik.tasks.middleware.StartupSignalsMiddleware", {}), 445 ("authentik.tasks.middleware.CurrentTask", {}), 446 ("authentik.tasks.middleware.TenantMiddleware", {}), 447 ("authentik.tasks.middleware.ModelDataMiddleware", {}), 448 ("authentik.tasks.middleware.TaskLogMiddleware", {}), 449 ("authentik.tasks.middleware.LoggingMiddleware", {}), 450 ("authentik.tasks.middleware.DescriptionMiddleware", {}), 451 ( 452 "authentik.tasks.middleware.MetricsMiddleware", 453 { 454 "prefix": "authentik", 455 }, 456 ), 457 ("django_dramatiq_postgres.middleware.TaskStateAfterMiddleware", {}), 458 ), 459 "test": TEST, 460} 461 462 463# Sentry integration 464 465env = get_env() 466_ERROR_REPORTING = CONFIG.get_bool("error_reporting.enabled", False) 467if _ERROR_REPORTING: 468 sentry_env = CONFIG.get("error_reporting.environment", "customer") 469 sentry_init(spotlight=DEBUG) 470 set_tag("authentik.uuid", sha512(str(SECRET_KEY).encode("ascii")).hexdigest()[:16]) 471 472 473# Static files (CSS, JavaScript, Images) 474# https://docs.djangoproject.com/en/2.1/howto/static-files/ 475 476STATICFILES_DIRS = [BASE_DIR / Path("web")] 477STATIC_URL = CONFIG.get("web.path", "/") + "static/" 478 479STORAGES = { 480 "staticfiles": { 481 "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage", 482 }, 483} 484 485# Django 5.2.8 and CVE-2025-64458 added a strong enforcement of 2048 characters 486# as the maximum for a URL to redirect to, mostly for running on Windows. 487# However, our URLs can easily exceed that with OAuth/SAML Query parameters or hash values. 488# 8192 should cover most cases. 489utils_http.MAX_URL_LENGTH = utils_http.MAX_URL_LENGTH * 4 490 491structlog_configure() 492LOGGING = get_logger_config() 493 494 495_DISALLOWED_ITEMS = [ 496 "SHARED_APPS", 497 "TENANT_APPS", 498 "INSTALLED_APPS", 499 "MIDDLEWARE_FIRST", 500 "MIDDLEWARE", 501 "MIDDLEWARE_LAST", 502 "AUTHENTICATION_BACKENDS", 503 "SPECTACULAR_SETTINGS", 504 "REST_FRAMEWORK", 505] 506 507SILENCED_SYSTEM_CHECKS = [ 508 # We use our own subclass of django.middleware.csrf.CsrfViewMiddleware 509 "security.W003", 510 # We don't set SESSION_COOKIE_SECURE since we use a custom SessionMiddleware subclass 511 "security.W010", 512 # HSTS: This is configured in reverse proxies/the go proxy, not in django 513 "security.W004", 514 # https redirect: This is configured in reverse proxies/the go proxy, not in django 515 "security.W008", 516] 517 518 519def subtract_list(a: list, b: list) -> list: 520 return [item for item in a if item not in b] 521 522 523def _filter_and_update(apps: list[str]) -> None: 524 for _app in set(apps): 525 if not _app.startswith("authentik"): 526 continue 527 _update_settings(f"{_app}.settings") 528 529 530def _update_settings(app_path: str) -> None: 531 try: 532 settings_module = importlib.import_module(app_path) 533 CONFIG.log("debug", "Loaded app settings", path=app_path) 534 535 new_shared_apps = subtract_list(getattr(settings_module, "SHARED_APPS", []), SHARED_APPS) 536 new_tenant_apps = subtract_list(getattr(settings_module, "TENANT_APPS", []), TENANT_APPS) 537 SHARED_APPS.extend(new_shared_apps) 538 TENANT_APPS.extend(new_tenant_apps) 539 _filter_and_update(new_shared_apps + new_tenant_apps) 540 541 MIDDLEWARE_FIRST.extend(getattr(settings_module, "MIDDLEWARE_FIRST", [])) 542 MIDDLEWARE.extend(getattr(settings_module, "MIDDLEWARE", [])) 543 544 AUTHENTICATION_BACKENDS.extend(getattr(settings_module, "AUTHENTICATION_BACKENDS", [])) 545 SPECTACULAR_SETTINGS.update(getattr(settings_module, "SPECTACULAR_SETTINGS", {})) 546 REST_FRAMEWORK.update(getattr(settings_module, "REST_FRAMEWORK", {})) 547 548 for _attr in dir(settings_module): 549 if not _attr.startswith("__") and _attr not in _DISALLOWED_ITEMS: 550 globals()[_attr] = getattr(settings_module, _attr) 551 except ImportError: 552 pass 553 554 555# Attempt to load enterprise app, if available 556try: 557 importlib.import_module("authentik.enterprise.apps") 558 CONFIG.log("info", "Enabled authentik enterprise") 559 TENANT_APPS.insert(TENANT_APPS.index("authentik.events"), "authentik.enterprise") 560except ImportError: 561 pass 562 563 564if DEBUG: 565 REST_FRAMEWORK["DEFAULT_RENDERER_CLASSES"].append( 566 "rest_framework.renderers.BrowsableAPIRenderer" 567 ) 568 SHARED_APPS.insert(SHARED_APPS.index("django.contrib.staticfiles"), "daphne") 569 enable_debug_trace(True) 570 571 572CONFIG.log("info", "Booting authentik", version=authentik_version()) 573 574# Load subapps's settings 575_filter_and_update(SHARED_APPS + TENANT_APPS) 576_update_settings("data.user_settings") 577 578MIDDLEWARE = list(OrderedDict.fromkeys(MIDDLEWARE_FIRST + MIDDLEWARE + MIDDLEWARE_LAST)) 579SHARED_APPS = list(OrderedDict.fromkeys(SHARED_APPS + TENANT_APPS)) 580INSTALLED_APPS = list(OrderedDict.fromkeys(SHARED_APPS + TENANT_APPS))
BASE_DIR =
PosixPath('/home/runner/work/authentik/authentik')
DEBUG =
False
SECRET_KEY =
'bTxssXkGczffpZo0gjyXqcJQlJUu7VSqkEevXv8m'
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_COOKIE_NAME =
'authentik_csrf'
CSRF_HEADER_NAME =
'HTTP_X_AUTHENTIK_CSRF'
LANGUAGE_COOKIE_NAME =
'authentik_language'
SESSION_COOKIE_NAME =
'authentik_session'
SESSION_COOKIE_DOMAIN =
None
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.stages.account_lockdown', '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.stages.account_lockdown', '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.8.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', 'AuthenticationEnum': 'authentik.flows.models.FlowAuthenticationRequirement', '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', 'RedirectURITypeEnum': 'authentik.providers.oauth2.models.RedirectURIType', '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.api.v3.schema.search.postprocess_schema_search_autocomplete', 'authentik.api.v3.schema.enum.postprocess_schema_enums']}
REST_FRAMEWORK =
{'DEFAULT_PAGINATION_CLASS': 'authentik.api.pagination.Pagination', 'DEFAULT_FILTER_BACKENDS': ['authentik.api.search.ql.QLSearch', 'authentik.rbac.filters.ObjectFilter', 'django_filters.rest_framework.DjangoFilterBackend', 'authentik.api.ordering.NullsAwareOrderingFilter'], '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_COOKIE_AGE =
86400.0
SESSION_EXPIRE_AT_BROWSER_CLOSE =
True
MESSAGE_STORAGE =
'authentik.root.ws.storage.ChannelsStorage'
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
TEST_RUNNER =
'authentik.root.test_runner.PytestTestRunner'
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, 'backend': <django_dramatiq_postgres.results.PostgresBackend object>}), ('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.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:
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.stages.account_lockdown', 'authentik.enterprise.stages.authenticator_endpoint_gdtc', 'authentik.enterprise.stages.mtls', 'authentik.enterprise.stages.source']