diff --git a/authentik/core/views/apps.py b/authentik/core/views/apps.py index d55bcef70..e52ba12d6 100644 --- a/authentik/core/views/apps.py +++ b/authentik/core/views/apps.py @@ -12,16 +12,19 @@ from authentik.flows.challenge import ( RedirectChallenge, ) from authentik.flows.exceptions import FlowNonApplicableException -from authentik.flows.models import in_memory_stage +from authentik.flows.models import FlowDesignation, in_memory_stage from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, FlowPlanner from authentik.flows.stage import ChallengeStageView -from authentik.flows.views.executor import SESSION_KEY_PLAN +from authentik.flows.views.executor import ( + SESSION_KEY_APPLICATION_PRE, + SESSION_KEY_PLAN, + ToDefaultFlow, +) from authentik.lib.utils.urls import redirect_with_qs from authentik.stages.consent.stage import ( PLAN_CONTEXT_CONSENT_HEADER, PLAN_CONTEXT_CONSENT_PERMISSIONS, ) -from authentik.tenants.models import Tenant class RedirectToAppLaunch(View): @@ -36,10 +39,10 @@ class RedirectToAppLaunch(View): # Check if we're authenticated already, saves us the flow run if request.user.is_authenticated: return HttpResponseRedirect(app.get_launch_url(request.user)) + self.request.session[SESSION_KEY_APPLICATION_PRE] = app # otherwise, do a custom flow plan that includes the application that's # being accessed, to improve usability - tenant: Tenant = request.tenant - flow = tenant.flow_authentication + flow = ToDefaultFlow(request=request, designation=FlowDesignation.AUTHENTICATION).get_flow() planner = FlowPlanner(flow) planner.allow_empty_flows = True try: diff --git a/authentik/flows/views/executor.py b/authentik/flows/views/executor.py index cb0d36317..04ac610cd 100644 --- a/authentik/flows/views/executor.py +++ b/authentik/flows/views/executor.py @@ -476,26 +476,32 @@ class ToDefaultFlow(View): LOGGER.debug("flow_by_policy: no flow found", filters=flow_filter) return None - def dispatch(self, request: HttpRequest) -> HttpResponse: - tenant: Tenant = request.tenant + def get_flow(self) -> Flow: + """Get a flow for the selected designation""" + tenant: Tenant = self.request.tenant flow = None # First, attempt to get default flow from tenant if self.designation == FlowDesignation.AUTHENTICATION: - # Attempt to get default flow from application - if SESSION_KEY_APPLICATION_PRE in self.request.session: - application: Application = self.request.session[SESSION_KEY_APPLICATION_PRE] - if application.provider: - flow = application.provider.authentication_flow - else: - flow = tenant.flow_authentication + flow = tenant.flow_authentication + # Check if we have a default flow from application + application: Optional[Application] = self.request.session.get( + SESSION_KEY_APPLICATION_PRE + ) + if application and application.provider and application.provider.authentication_flow: + flow = application.provider.authentication_flow elif self.designation == FlowDesignation.INVALIDATION: flow = tenant.flow_invalidation + if flow: + return flow # If no flow was set, get the first based on slug and policy - if not flow: - flow = self.flow_by_policy(request, designation=self.designation) + flow = self.flow_by_policy(self.request, designation=self.designation) + if flow: + return flow # If we still don't have a flow, 404 - if not flow: - raise Http404 + raise Http404 + + def dispatch(self, request: HttpRequest) -> HttpResponse: + flow = self.get_flow() # If user already has a pending plan, clear it so we don't have to later. if SESSION_KEY_PLAN in self.request.session: plan: FlowPlan = self.request.session[SESSION_KEY_PLAN]