authentik.core.views.apps
app views
1"""app views""" 2 3from django.http import Http404, HttpRequest, HttpResponse, HttpResponseRedirect 4from django.shortcuts import get_object_or_404 5from django.utils.translation import gettext_lazy as _ 6from django.views import View 7 8from authentik.core.models import Application 9from authentik.flows.challenge import ( 10 ChallengeResponse, 11 HttpChallengeResponse, 12 RedirectChallenge, 13) 14from authentik.flows.exceptions import FlowNonApplicableException 15from authentik.flows.models import FlowDesignation, in_memory_stage 16from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, FlowPlanner 17from authentik.flows.stage import ChallengeStageView 18from authentik.flows.views.executor import ( 19 ToDefaultFlow, 20) 21from authentik.stages.consent.stage import ( 22 PLAN_CONTEXT_CONSENT_HEADER, 23 PLAN_CONTEXT_CONSENT_PERMISSIONS, 24) 25 26 27class RedirectToAppLaunch(View): 28 """Application launch view, redirect to the launch URL""" 29 30 def dispatch(self, request: HttpRequest, application_slug: str) -> HttpResponse: 31 app = get_object_or_404(Application, slug=application_slug) 32 # Check here if the application has any launch URL set, if not 404 33 launch = app.get_launch_url() 34 if not launch: 35 raise Http404 36 # Check if we're authenticated already, saves us the flow run 37 if request.user.is_authenticated: 38 return HttpResponseRedirect(app.get_launch_url(request.user)) 39 # otherwise, do a custom flow plan that includes the application that's 40 # being accessed, to improve usability 41 if app and app.provider and app.provider.authentication_flow: 42 flow = app.provider.authentication_flow 43 else: 44 flow = ToDefaultFlow.get_flow( 45 request=request, designation=FlowDesignation.AUTHENTICATION 46 ) 47 planner = FlowPlanner(flow) 48 planner.allow_empty_flows = True 49 try: 50 plan = planner.plan( 51 request, 52 { 53 PLAN_CONTEXT_APPLICATION: app, 54 PLAN_CONTEXT_CONSENT_HEADER: _("You're about to sign into %(application)s.") 55 % {"application": app.name}, 56 PLAN_CONTEXT_CONSENT_PERMISSIONS: [], 57 }, 58 ) 59 except FlowNonApplicableException: 60 raise Http404 from None 61 # We redirect with an in_memory stage instead of `?next=...` as the launch URL 62 # might be formatted with the user, which hasn't logged in yet 63 plan.append_stage(in_memory_stage(RedirectToAppStage)) 64 return plan.to_redirect(request, flow) 65 66 67class RedirectToAppStage(ChallengeStageView): 68 """Final stage to be inserted after the user logs in""" 69 70 def get_challenge(self, *args, **kwargs) -> RedirectChallenge: 71 app = self.executor.plan.context[PLAN_CONTEXT_APPLICATION] 72 launch = app.get_launch_url(self.get_pending_user()) 73 # sanity check to ensure launch is still set 74 if not launch: 75 raise Http404 76 return RedirectChallenge( 77 instance={ 78 "to": launch, 79 } 80 ) 81 82 def challenge_valid(self, response: ChallengeResponse) -> HttpResponse: 83 return HttpChallengeResponse(self.get_challenge())
class
RedirectToAppLaunch(django.views.generic.base.View):
28class RedirectToAppLaunch(View): 29 """Application launch view, redirect to the launch URL""" 30 31 def dispatch(self, request: HttpRequest, application_slug: str) -> HttpResponse: 32 app = get_object_or_404(Application, slug=application_slug) 33 # Check here if the application has any launch URL set, if not 404 34 launch = app.get_launch_url() 35 if not launch: 36 raise Http404 37 # Check if we're authenticated already, saves us the flow run 38 if request.user.is_authenticated: 39 return HttpResponseRedirect(app.get_launch_url(request.user)) 40 # otherwise, do a custom flow plan that includes the application that's 41 # being accessed, to improve usability 42 if app and app.provider and app.provider.authentication_flow: 43 flow = app.provider.authentication_flow 44 else: 45 flow = ToDefaultFlow.get_flow( 46 request=request, designation=FlowDesignation.AUTHENTICATION 47 ) 48 planner = FlowPlanner(flow) 49 planner.allow_empty_flows = True 50 try: 51 plan = planner.plan( 52 request, 53 { 54 PLAN_CONTEXT_APPLICATION: app, 55 PLAN_CONTEXT_CONSENT_HEADER: _("You're about to sign into %(application)s.") 56 % {"application": app.name}, 57 PLAN_CONTEXT_CONSENT_PERMISSIONS: [], 58 }, 59 ) 60 except FlowNonApplicableException: 61 raise Http404 from None 62 # We redirect with an in_memory stage instead of `?next=...` as the launch URL 63 # might be formatted with the user, which hasn't logged in yet 64 plan.append_stage(in_memory_stage(RedirectToAppStage)) 65 return plan.to_redirect(request, flow)
Application launch view, redirect to the launch URL
def
dispatch( self, request: django.http.request.HttpRequest, application_slug: str) -> django.http.response.HttpResponse:
31 def dispatch(self, request: HttpRequest, application_slug: str) -> HttpResponse: 32 app = get_object_or_404(Application, slug=application_slug) 33 # Check here if the application has any launch URL set, if not 404 34 launch = app.get_launch_url() 35 if not launch: 36 raise Http404 37 # Check if we're authenticated already, saves us the flow run 38 if request.user.is_authenticated: 39 return HttpResponseRedirect(app.get_launch_url(request.user)) 40 # otherwise, do a custom flow plan that includes the application that's 41 # being accessed, to improve usability 42 if app and app.provider and app.provider.authentication_flow: 43 flow = app.provider.authentication_flow 44 else: 45 flow = ToDefaultFlow.get_flow( 46 request=request, designation=FlowDesignation.AUTHENTICATION 47 ) 48 planner = FlowPlanner(flow) 49 planner.allow_empty_flows = True 50 try: 51 plan = planner.plan( 52 request, 53 { 54 PLAN_CONTEXT_APPLICATION: app, 55 PLAN_CONTEXT_CONSENT_HEADER: _("You're about to sign into %(application)s.") 56 % {"application": app.name}, 57 PLAN_CONTEXT_CONSENT_PERMISSIONS: [], 58 }, 59 ) 60 except FlowNonApplicableException: 61 raise Http404 from None 62 # We redirect with an in_memory stage instead of `?next=...` as the launch URL 63 # might be formatted with the user, which hasn't logged in yet 64 plan.append_stage(in_memory_stage(RedirectToAppStage)) 65 return plan.to_redirect(request, flow)
68class RedirectToAppStage(ChallengeStageView): 69 """Final stage to be inserted after the user logs in""" 70 71 def get_challenge(self, *args, **kwargs) -> RedirectChallenge: 72 app = self.executor.plan.context[PLAN_CONTEXT_APPLICATION] 73 launch = app.get_launch_url(self.get_pending_user()) 74 # sanity check to ensure launch is still set 75 if not launch: 76 raise Http404 77 return RedirectChallenge( 78 instance={ 79 "to": launch, 80 } 81 ) 82 83 def challenge_valid(self, response: ChallengeResponse) -> HttpResponse: 84 return HttpChallengeResponse(self.get_challenge())
Final stage to be inserted after the user logs in
71 def get_challenge(self, *args, **kwargs) -> RedirectChallenge: 72 app = self.executor.plan.context[PLAN_CONTEXT_APPLICATION] 73 launch = app.get_launch_url(self.get_pending_user()) 74 # sanity check to ensure launch is still set 75 if not launch: 76 raise Http404 77 return RedirectChallenge( 78 instance={ 79 "to": launch, 80 } 81 )
Return the challenge that the client should solve
def
challenge_valid( self, response: authentik.flows.challenge.ChallengeResponse) -> django.http.response.HttpResponse:
83 def challenge_valid(self, response: ChallengeResponse) -> HttpResponse: 84 return HttpChallengeResponse(self.get_challenge())
Callback when the challenge has the correct format