authentik.core.signals

authentik core signals

 1"""authentik core signals"""
 2
 3from channels.layers import get_channel_layer
 4from django.contrib.auth.signals import user_logged_in
 5from django.core.cache import cache
 6from django.db.models import Model
 7from django.db.models.signals import post_delete, post_save, pre_save
 8from django.dispatch import Signal, receiver
 9from django.http.request import HttpRequest
10from structlog.stdlib import get_logger
11
12from authentik.core.models import (
13    Application,
14    AuthenticatedSession,
15    BackchannelProvider,
16    ExpiringModel,
17    Session,
18    User,
19    default_token_duration,
20)
21from authentik.flows.apps import RefreshOtherFlowsAfterAuthentication
22from authentik.root.ws.consumer import build_device_group
23
24# Arguments: user: User, password: str
25password_changed = Signal()
26# Arguments: user: User, request: HttpRequest | None
27password_hash_changed = Signal()
28# Arguments: credentials: dict[str, any], request: HttpRequest,
29#            stage: Stage, context: dict[str, any]
30login_failed = Signal()
31
32LOGGER = get_logger()
33
34
35@receiver(post_save, sender=Application)
36def post_save_application(sender: type[Model], instance, created: bool, **_):
37    """Clear user's application cache upon application creation"""
38    from authentik.core.api.applications import user_app_cache_key
39
40    if not created:  # pragma: no cover
41        return
42
43    # Also delete user application cache
44    keys = cache.keys(user_app_cache_key("*"))
45    cache.delete_many(keys)
46
47
48@receiver(user_logged_in)
49def user_logged_in_session(sender, request: HttpRequest, user: User, **_):
50    """Create an AuthenticatedSession from request"""
51
52    session = AuthenticatedSession.from_request(request, user)
53    if session:
54        session.save()
55
56    if not RefreshOtherFlowsAfterAuthentication.get():
57        return
58    layer = get_channel_layer()
59    device_cookie = request.COOKIES.get("authentik_device")
60    if device_cookie:
61        layer.group_send_blocking(
62            build_device_group(device_cookie),
63            {"type": "event.session.authenticated"},
64        )
65
66
67@receiver(post_delete, sender=AuthenticatedSession)
68def authenticated_session_delete(sender: type[Model], instance: AuthenticatedSession, **_):
69    """Delete session when authenticated session is deleted"""
70    Session.objects.filter(session_key=instance.pk).delete()
71
72
73@receiver(pre_save)
74def backchannel_provider_pre_save(sender: type[Model], instance: Model, **_):
75    """Ensure backchannel providers have is_backchannel set to true"""
76    if not isinstance(instance, BackchannelProvider):
77        return
78    instance.is_backchannel = True
79
80
81@receiver(pre_save)
82def expiring_model_pre_save(sender: type[Model], instance: Model, **_):
83    """Ensure expires is set on ExpiringModels that are set to expire"""
84    if not issubclass(sender, ExpiringModel):
85        return
86    if instance.expiring and instance.expires is None:
87        instance.expires = default_token_duration()
password_changed = <django.dispatch.dispatcher.Signal object>
password_hash_changed = <django.dispatch.dispatcher.Signal object>
login_failed = <django.dispatch.dispatcher.Signal object>
LOGGER = <BoundLoggerLazyProxy(logger=None, wrapper_class=None, processors=None, context_class=None, initial_values={}, logger_factory_args=())>
@receiver(post_save, sender=Application)
def post_save_application( sender: type[django.db.models.base.Model], instance, created: bool, **_):
36@receiver(post_save, sender=Application)
37def post_save_application(sender: type[Model], instance, created: bool, **_):
38    """Clear user's application cache upon application creation"""
39    from authentik.core.api.applications import user_app_cache_key
40
41    if not created:  # pragma: no cover
42        return
43
44    # Also delete user application cache
45    keys = cache.keys(user_app_cache_key("*"))
46    cache.delete_many(keys)

Clear user's application cache upon application creation

@receiver(user_logged_in)
def user_logged_in_session( sender, request: django.http.request.HttpRequest, user: authentik.core.models.User, **_):
49@receiver(user_logged_in)
50def user_logged_in_session(sender, request: HttpRequest, user: User, **_):
51    """Create an AuthenticatedSession from request"""
52
53    session = AuthenticatedSession.from_request(request, user)
54    if session:
55        session.save()
56
57    if not RefreshOtherFlowsAfterAuthentication.get():
58        return
59    layer = get_channel_layer()
60    device_cookie = request.COOKIES.get("authentik_device")
61    if device_cookie:
62        layer.group_send_blocking(
63            build_device_group(device_cookie),
64            {"type": "event.session.authenticated"},
65        )

Create an AuthenticatedSession from request

@receiver(post_delete, sender=AuthenticatedSession)
def authenticated_session_delete( sender: type[django.db.models.base.Model], instance: authentik.core.models.AuthenticatedSession, **_):
68@receiver(post_delete, sender=AuthenticatedSession)
69def authenticated_session_delete(sender: type[Model], instance: AuthenticatedSession, **_):
70    """Delete session when authenticated session is deleted"""
71    Session.objects.filter(session_key=instance.pk).delete()

Delete session when authenticated session is deleted

@receiver(pre_save)
def backchannel_provider_pre_save( sender: type[django.db.models.base.Model], instance: django.db.models.base.Model, **_):
74@receiver(pre_save)
75def backchannel_provider_pre_save(sender: type[Model], instance: Model, **_):
76    """Ensure backchannel providers have is_backchannel set to true"""
77    if not isinstance(instance, BackchannelProvider):
78        return
79    instance.is_backchannel = True

Ensure backchannel providers have is_backchannel set to true

@receiver(pre_save)
def expiring_model_pre_save( sender: type[django.db.models.base.Model], instance: django.db.models.base.Model, **_):
82@receiver(pre_save)
83def expiring_model_pre_save(sender: type[Model], instance: Model, **_):
84    """Ensure expires is set on ExpiringModels that are set to expire"""
85    if not issubclass(sender, ExpiringModel):
86        return
87    if instance.expiring and instance.expires is None:
88        instance.expires = default_token_duration()

Ensure expires is set on ExpiringModels that are set to expire