authentik.providers.oauth2.tasks

OAuth2 Provider Tasks

 1"""OAuth2 Provider Tasks"""
 2
 3from django.utils.translation import gettext_lazy as _
 4from dramatiq.actor import actor
 5from structlog.stdlib import get_logger
 6
 7from authentik.lib.utils.http import get_http_session
 8from authentik.providers.oauth2.models import OAuth2LogoutMethod, OAuth2Provider
 9from authentik.providers.oauth2.utils import create_logout_token
10from authentik.tasks.middleware import CurrentTask
11
12LOGGER = get_logger()
13
14
15@actor(description=_("Send a back-channel logout request to the registered client"))
16def send_backchannel_logout_request(
17    provider_pk: int,
18    iss: str,
19    sub: str | None = None,
20    session_key: str | None = None,
21) -> bool:
22    """Send a back-channel logout request to the registered client
23
24    Args:
25        provider_pk: The OAuth2 provider's primary key
26        iss: The issuer URL for the logout token
27        sub: The subject identifier to include in the logout token
28        session_key: The authentik session key to hash and include in the logout token
29
30    Returns:
31        bool: True if the request was sent successfully, False otherwise
32    """
33    self = CurrentTask.get_task()
34    LOGGER.debug("Sending back-channel logout request", provider_pk=provider_pk, sub=sub)
35
36    provider = OAuth2Provider.objects.filter(pk=provider_pk).first()
37    if provider is None:
38        return
39
40    # Generate the logout token
41    logout_token = create_logout_token(provider, iss, sub, session_key)
42
43    if provider.logout_method != OAuth2LogoutMethod.BACKCHANNEL:
44        self.info("Provider not configured for back-channel logout")
45        return
46
47    if not provider.logout_uri:
48        self.info("No logout URI configured for provider")
49        return
50
51    # Send the back-channel logout request
52    response = get_http_session().post(
53        provider.logout_uri,
54        data={"logout_token": logout_token},
55        headers={"Content-Type": "application/x-www-form-urlencoded"},
56        allow_redirects=True,
57    )
58    response.raise_for_status()
59
60    self.info("Back-channel logout successful", sub=sub)
61    return True
62
63
64@actor(description=_("Handle backchannel logout notifications dispatched via signal"))
65def backchannel_logout_notification_dispatch(revocations: list, **kwargs):
66    """Handle backchannel logout notifications dispatched via signal"""
67    for revocation in revocations:
68        provider_pk, iss, sub, session_key = revocation
69        provider = OAuth2Provider.objects.filter(pk=provider_pk).first()
70        send_backchannel_logout_request.send_with_options(
71            args=(provider_pk, iss, sub, session_key),
72            rel_obj=provider,
73        )
LOGGER = <BoundLoggerLazyProxy(logger=None, wrapper_class=None, processors=None, context_class=None, initial_values={}, logger_factory_args=())>
send_backchannel_logout_request = Actor(<function send_backchannel_logout_request>, queue_name='default', actor_name='send_backchannel_logout_request')

Send a back-channel logout request to the registered client

Args: provider_pk: The OAuth2 provider's primary key iss: The issuer URL for the logout token sub: The subject identifier to include in the logout token session_key: The authentik session key to hash and include in the logout token

Returns: bool: True if the request was sent successfully, False otherwise

backchannel_logout_notification_dispatch = Actor(<function backchannel_logout_notification_dispatch>, queue_name='default', actor_name='backchannel_logout_notification_dispatch')

Handle backchannel logout notifications dispatched via signal