def handle_login_flow( self, source: SAMLSource, *stages_to_append, **kwargs ) -> HttpResponse: """Prepare Authentication Plan, redirect user FlowExecutor""" # Ensure redirect is carried through when user was trying to # authorize application final_redirect = self.request.session.get(SESSION_KEY_GET, {}).get( NEXT_ARG_NAME, "authentik_core:if-admin" ) kwargs.update( { PLAN_CONTEXT_SSO: True, PLAN_CONTEXT_SOURCE: source, PLAN_CONTEXT_REDIRECT: final_redirect, } ) # We run the Flow planner here so we can pass the Pending user in the context planner = FlowPlanner(source.pre_authentication_flow) planner.allow_empty_flows = True plan = planner.plan(self.request, kwargs) for stage in stages_to_append: plan.append(stage) self.request.session[SESSION_KEY_PLAN] = plan return redirect_with_qs( "authentik_core:if-flow", self.request.GET, flow_slug=source.pre_authentication_flow.slug, )
def get(self, request: HttpRequest, application_slug: str) -> HttpResponse: """Verify the SAML Request, and if valid initiate the FlowPlanner for the application""" # Call the method handler, which checks the SAML # Request and returns a HTTP Response on error method_response = self.check_saml_request() if method_response: return method_response # Regardless, we start the planner and return to it planner = FlowPlanner(self.provider.authorization_flow) planner.allow_empty_flows = True plan = planner.plan( request, { PLAN_CONTEXT_SSO: True, PLAN_CONTEXT_APPLICATION: self.application, PLAN_CONTEXT_CONSENT_HEADER: _("You're about to sign into %(application)s.") % { "application": self.application.name }, PLAN_CONTEXT_CONSENT_PERMISSIONS: [], }, ) plan.append(in_memory_stage(SAMLFlowFinalView)) request.session[SESSION_KEY_PLAN] = plan return redirect_with_qs( "authentik_core:if-flow", request.GET, flow_slug=self.provider.authorization_flow.slug, )
def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: """Start FlowPLanner, return to flow executor shell""" # After we've checked permissions, and the user has access, check if we need # to re-authenticate the user if self.params.max_age: current_age: timedelta = ( timezone.now() - Event.objects.filter( action=EventAction.LOGIN, user=get_user(self.request.user) ) .latest("created") .created ) if current_age.total_seconds() > self.params.max_age: return self.handle_no_permission() # If prompt=login, we need to re-authenticate the user regardless if ( PROMPT_LOGIN in self.params.prompt and SESSION_NEEDS_LOGIN not in self.request.session ): self.request.session[SESSION_NEEDS_LOGIN] = True return self.handle_no_permission() # Regardless, we start the planner and return to it planner = FlowPlanner(self.provider.authorization_flow) # planner.use_cache = False planner.allow_empty_flows = True scope_descriptions = UserInfoView().get_scope_descriptions(self.params.scope) plan: FlowPlan = planner.plan( self.request, { PLAN_CONTEXT_SSO: True, PLAN_CONTEXT_APPLICATION: self.application, # OAuth2 related params PLAN_CONTEXT_PARAMS: self.params, # Consent related params PLAN_CONTEXT_CONSENT_HEADER: _( "You're about to sign into %(application)s." ) % {"application": self.application.name}, PLAN_CONTEXT_CONSENT_PERMISSIONS: scope_descriptions, }, ) # OpenID clients can specify a `prompt` parameter, and if its set to consent we # need to inject a consent stage if PROMPT_CONSNET in self.params.prompt: if not any(isinstance(x, ConsentStageView) for x in plan.stages): # Plan does not have any consent stage, so we add an in-memory one stage = ConsentStage( name="OAuth2 Provider In-memory consent stage", mode=ConsentMode.ALWAYS_REQUIRE, ) plan.append(stage) plan.append(in_memory_stage(OAuthFulfillmentStage)) self.request.session[SESSION_KEY_PLAN] = plan return redirect_with_qs( "authentik_core:if-flow", self.request.GET, flow_slug=self.provider.authorization_flow.slug, )