Compare commits
	
		
			1 Commits
		
	
	
		
			version/20
			...
			flows/conc
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 5797a51993 | 
| @ -54,6 +54,7 @@ class Challenge(PassiveSerializer): | |||||||
|  |  | ||||||
|     flow_info = ContextualFlowInfo(required=False) |     flow_info = ContextualFlowInfo(required=False) | ||||||
|     component = CharField(default="") |     component = CharField(default="") | ||||||
|  |     xid = CharField(required=False) | ||||||
|  |  | ||||||
|     response_errors = DictField( |     response_errors = DictField( | ||||||
|         child=ErrorDetailSerializer(many=True), allow_empty=True, required=False |         child=ErrorDetailSerializer(many=True), allow_empty=True, required=False | ||||||
|  | |||||||
| @ -143,10 +143,12 @@ class FlowPlan: | |||||||
|         request: HttpRequest, |         request: HttpRequest, | ||||||
|         flow: Flow, |         flow: Flow, | ||||||
|         allowed_silent_types: list["StageView"] | None = None, |         allowed_silent_types: list["StageView"] | None = None, | ||||||
|  |         **get_params, | ||||||
|     ) -> HttpResponse: |     ) -> HttpResponse: | ||||||
|         """Redirect to the flow executor for this flow plan""" |         """Redirect to the flow executor for this flow plan""" | ||||||
|         from authentik.flows.views.executor import ( |         from authentik.flows.views.executor import ( | ||||||
|             SESSION_KEY_PLAN, |             SESSION_KEY_PLAN, | ||||||
|  |             FlowContainer, | ||||||
|             FlowExecutorView, |             FlowExecutorView, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
| @ -157,6 +159,7 @@ class FlowPlan: | |||||||
|             # No unskippable stages found, so we can directly return the response of the last stage |             # No unskippable stages found, so we can directly return the response of the last stage | ||||||
|             final_stage: type[StageView] = self.bindings[-1].stage.view |             final_stage: type[StageView] = self.bindings[-1].stage.view | ||||||
|             temp_exec = FlowExecutorView(flow=flow, request=request, plan=self) |             temp_exec = FlowExecutorView(flow=flow, request=request, plan=self) | ||||||
|  |             temp_exec.container = FlowContainer(request) | ||||||
|             temp_exec.current_stage = self.bindings[-1].stage |             temp_exec.current_stage = self.bindings[-1].stage | ||||||
|             temp_exec.current_stage_view = final_stage |             temp_exec.current_stage_view = final_stage | ||||||
|             temp_exec.setup(request, flow.slug) |             temp_exec.setup(request, flow.slug) | ||||||
| @ -174,6 +177,9 @@ class FlowPlan: | |||||||
|         ): |         ): | ||||||
|             get_qs["inspector"] = "available" |             get_qs["inspector"] = "available" | ||||||
|  |  | ||||||
|  |         for key, value in get_params: | ||||||
|  |             get_qs[key] = value | ||||||
|  |  | ||||||
|         return redirect_with_qs( |         return redirect_with_qs( | ||||||
|             "authentik_core:if-flow", |             "authentik_core:if-flow", | ||||||
|             get_qs, |             get_qs, | ||||||
|  | |||||||
| @ -191,6 +191,7 @@ class ChallengeStageView(StageView): | |||||||
|                 ) |                 ) | ||||||
|                 flow_info.is_valid() |                 flow_info.is_valid() | ||||||
|                 challenge.initial_data["flow_info"] = flow_info.data |                 challenge.initial_data["flow_info"] = flow_info.data | ||||||
|  |             challenge.initial_data["xid"] = self.executor.container.exec_id | ||||||
|             if isinstance(challenge, WithUserInfoChallenge): |             if isinstance(challenge, WithUserInfoChallenge): | ||||||
|                 # If there's a pending user, update the `username` field |                 # If there's a pending user, update the `username` field | ||||||
|                 # this field is only used by password managers. |                 # this field is only used by password managers. | ||||||
|  | |||||||
| @ -28,7 +28,7 @@ window.authentik.flow = { | |||||||
|  |  | ||||||
| {% block body %} | {% block body %} | ||||||
| <ak-message-container></ak-message-container> | <ak-message-container></ak-message-container> | ||||||
| <ak-flow-executor flowSlug="{{ flow.slug }}"> | <ak-flow-executor flowSlug="{{ flow.slug }}" xid="{{ xid }}"> | ||||||
|     <ak-loading></ak-loading> |     <ak-loading></ak-loading> | ||||||
| </ak-flow-executor> | </ak-flow-executor> | ||||||
| {% endblock %} | {% endblock %} | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| """authentik multi-stage authentication engine""" | """authentik multi-stage authentication engine""" | ||||||
|  |  | ||||||
| from copy import deepcopy | from copy import deepcopy | ||||||
|  | from uuid import uuid4 | ||||||
|  |  | ||||||
| from django.conf import settings | from django.conf import settings | ||||||
| from django.contrib.auth.mixins import LoginRequiredMixin | from django.contrib.auth.mixins import LoginRequiredMixin | ||||||
| @ -64,6 +65,7 @@ from authentik.policies.engine import PolicyEngine | |||||||
| LOGGER = get_logger() | LOGGER = get_logger() | ||||||
| # Argument used to redirect user after login | # Argument used to redirect user after login | ||||||
| NEXT_ARG_NAME = "next" | NEXT_ARG_NAME = "next" | ||||||
|  | SESSION_KEY_PLAN_CONTAINER = "authentik/flows/plan_container/%s" | ||||||
| SESSION_KEY_PLAN = "authentik/flows/plan" | SESSION_KEY_PLAN = "authentik/flows/plan" | ||||||
| SESSION_KEY_APPLICATION_PRE = "authentik/flows/application_pre" | SESSION_KEY_APPLICATION_PRE = "authentik/flows/application_pre" | ||||||
| SESSION_KEY_GET = "authentik/flows/get" | SESSION_KEY_GET = "authentik/flows/get" | ||||||
| @ -71,6 +73,7 @@ SESSION_KEY_POST = "authentik/flows/post" | |||||||
| SESSION_KEY_HISTORY = "authentik/flows/history" | SESSION_KEY_HISTORY = "authentik/flows/history" | ||||||
| QS_KEY_TOKEN = "flow_token"  # nosec | QS_KEY_TOKEN = "flow_token"  # nosec | ||||||
| QS_QUERY = "query" | QS_QUERY = "query" | ||||||
|  | QS_EXEC_ID = "xid" | ||||||
|  |  | ||||||
|  |  | ||||||
| def challenge_types(): | def challenge_types(): | ||||||
| @ -97,6 +100,88 @@ class InvalidStageError(SentryIgnoredException): | |||||||
|     """Error raised when a challenge from a stage is not valid""" |     """Error raised when a challenge from a stage is not valid""" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class FlowContainer: | ||||||
|  |     """Allow for multiple concurrent flow executions in the same session""" | ||||||
|  |  | ||||||
|  |     def __init__(self, request: HttpRequest, exec_id: str | None = None) -> None: | ||||||
|  |         self.request = request | ||||||
|  |         self.exec_id = exec_id | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def new(request: HttpRequest): | ||||||
|  |         exec_id = str(uuid4()) | ||||||
|  |         request.session[SESSION_KEY_PLAN_CONTAINER % exec_id] = {} | ||||||
|  |         return FlowContainer(request, exec_id) | ||||||
|  |  | ||||||
|  |     def exists(self) -> bool: | ||||||
|  |         """Check if flow exists in container/session""" | ||||||
|  |         return SESSION_KEY_PLAN in self.session | ||||||
|  |  | ||||||
|  |     def save(self): | ||||||
|  |         self.request.session.modified = True | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def session(self): | ||||||
|  |         # Backwards compatibility: store session plan/etc directly in session | ||||||
|  |         if not self.exec_id: | ||||||
|  |             return self.request.session | ||||||
|  |         self.request.session.setdefault(SESSION_KEY_PLAN_CONTAINER % self.exec_id, {}) | ||||||
|  |         return self.request.session.get(SESSION_KEY_PLAN_CONTAINER % self.exec_id, {}) | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def plan(self) -> FlowPlan: | ||||||
|  |         return self.session.get(SESSION_KEY_PLAN) | ||||||
|  |  | ||||||
|  |     def to_redirect( | ||||||
|  |         self, | ||||||
|  |         request: HttpRequest, | ||||||
|  |         flow: Flow, | ||||||
|  |         allowed_silent_types: list[StageView] | None = None, | ||||||
|  |         **get_params, | ||||||
|  |     ) -> HttpResponse: | ||||||
|  |         get_params[QS_EXEC_ID] = self.exec_id | ||||||
|  |         return self.plan.to_redirect( | ||||||
|  |             request, flow, allowed_silent_types=allowed_silent_types, **get_params | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     @plan.setter | ||||||
|  |     def plan(self, value: FlowPlan): | ||||||
|  |         self.session[SESSION_KEY_PLAN] = value | ||||||
|  |         self.request.session.modified = True | ||||||
|  |         self.save() | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def application_pre(self): | ||||||
|  |         return self.session.get(SESSION_KEY_APPLICATION_PRE) | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def get(self) -> QueryDict: | ||||||
|  |         return self.session.get(SESSION_KEY_GET) | ||||||
|  |  | ||||||
|  |     @get.setter | ||||||
|  |     def get(self, value: QueryDict): | ||||||
|  |         self.session[SESSION_KEY_GET] = value | ||||||
|  |         self.save() | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def post(self) -> QueryDict: | ||||||
|  |         return self.session.get(SESSION_KEY_POST) | ||||||
|  |  | ||||||
|  |     @post.setter | ||||||
|  |     def post(self, value: QueryDict): | ||||||
|  |         self.session[SESSION_KEY_POST] = value | ||||||
|  |         self.save() | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def history(self) -> list[FlowPlan]: | ||||||
|  |         return self.session.get(SESSION_KEY_HISTORY) | ||||||
|  |  | ||||||
|  |     @history.setter | ||||||
|  |     def history(self, value: list[FlowPlan]): | ||||||
|  |         self.session[SESSION_KEY_HISTORY] = value | ||||||
|  |         self.save() | ||||||
|  |  | ||||||
|  |  | ||||||
| @method_decorator(xframe_options_sameorigin, name="dispatch") | @method_decorator(xframe_options_sameorigin, name="dispatch") | ||||||
| class FlowExecutorView(APIView): | class FlowExecutorView(APIView): | ||||||
|     """Flow executor, passing requests to Stage Views""" |     """Flow executor, passing requests to Stage Views""" | ||||||
| @ -104,8 +189,9 @@ class FlowExecutorView(APIView): | |||||||
|     permission_classes = [AllowAny] |     permission_classes = [AllowAny] | ||||||
|  |  | ||||||
|     flow: Flow = None |     flow: Flow = None | ||||||
|  |  | ||||||
|     plan: FlowPlan | None = None |     plan: FlowPlan | None = None | ||||||
|  |     container: FlowContainer | ||||||
|  |  | ||||||
|     current_binding: FlowStageBinding | None = None |     current_binding: FlowStageBinding | None = None | ||||||
|     current_stage: Stage |     current_stage: Stage | ||||||
|     current_stage_view: View |     current_stage_view: View | ||||||
| @ -160,10 +246,12 @@ class FlowExecutorView(APIView): | |||||||
|             if QS_KEY_TOKEN in get_params: |             if QS_KEY_TOKEN in get_params: | ||||||
|                 plan = self._check_flow_token(get_params[QS_KEY_TOKEN]) |                 plan = self._check_flow_token(get_params[QS_KEY_TOKEN]) | ||||||
|                 if plan: |                 if plan: | ||||||
|                     self.request.session[SESSION_KEY_PLAN] = plan |                     container = FlowContainer.new(request) | ||||||
|  |                     container.plan = plan | ||||||
|             # Early check if there's an active Plan for the current session |             # Early check if there's an active Plan for the current session | ||||||
|             if SESSION_KEY_PLAN in self.request.session: |             self.container = FlowContainer(request, request.GET.get(QS_EXEC_ID)) | ||||||
|                 self.plan: FlowPlan = self.request.session[SESSION_KEY_PLAN] |             if self.container.exists(): | ||||||
|  |                 self.plan: FlowPlan = self.container.plan | ||||||
|                 if self.plan.flow_pk != self.flow.pk.hex: |                 if self.plan.flow_pk != self.flow.pk.hex: | ||||||
|                     self._logger.warning( |                     self._logger.warning( | ||||||
|                         "f(exec): Found existing plan for other flow, deleting plan", |                         "f(exec): Found existing plan for other flow, deleting plan", | ||||||
| @ -176,13 +264,14 @@ class FlowExecutorView(APIView): | |||||||
|                     self._logger.debug("f(exec): Continuing existing plan") |                     self._logger.debug("f(exec): Continuing existing plan") | ||||||
|  |  | ||||||
|             # Initial flow request, check if we have an upstream query string passed in |             # Initial flow request, check if we have an upstream query string passed in | ||||||
|             request.session[SESSION_KEY_GET] = get_params |             self.container.get = get_params | ||||||
|             # Don't check session again as we've either already loaded the plan or we need to plan |             # Don't check session again as we've either already loaded the plan or we need to plan | ||||||
|             if not self.plan: |             if not self.plan: | ||||||
|                 request.session[SESSION_KEY_HISTORY] = [] |                 self.container.history = [] | ||||||
|                 self._logger.debug("f(exec): No active Plan found, initiating planner") |                 self._logger.debug("f(exec): No active Plan found, initiating planner") | ||||||
|                 try: |                 try: | ||||||
|                     self.plan = self._initiate_plan() |                     self.plan = self._initiate_plan() | ||||||
|  |                     self.container.plan = self.plan | ||||||
|                 except FlowNonApplicableException as exc: |                 except FlowNonApplicableException as exc: | ||||||
|                     self._logger.warning("f(exec): Flow not applicable to current user", exc=exc) |                     self._logger.warning("f(exec): Flow not applicable to current user", exc=exc) | ||||||
|                     return self.handle_invalid_flow(exc) |                     return self.handle_invalid_flow(exc) | ||||||
| @ -254,12 +343,19 @@ class FlowExecutorView(APIView): | |||||||
|         request=OpenApiTypes.NONE, |         request=OpenApiTypes.NONE, | ||||||
|         parameters=[ |         parameters=[ | ||||||
|             OpenApiParameter( |             OpenApiParameter( | ||||||
|                 name="query", |                 name=QS_QUERY, | ||||||
|                 location=OpenApiParameter.QUERY, |                 location=OpenApiParameter.QUERY, | ||||||
|                 required=True, |                 required=True, | ||||||
|                 description="Querystring as received", |                 description="Querystring as received", | ||||||
|                 type=OpenApiTypes.STR, |                 type=OpenApiTypes.STR, | ||||||
|             ) |             ), | ||||||
|  |             OpenApiParameter( | ||||||
|  |                 name=QS_EXEC_ID, | ||||||
|  |                 location=OpenApiParameter.QUERY, | ||||||
|  |                 required=False, | ||||||
|  |                 description="Flow execution ID", | ||||||
|  |                 type=OpenApiTypes.STR, | ||||||
|  |             ), | ||||||
|         ], |         ], | ||||||
|         operation_id="flows_executor_get", |         operation_id="flows_executor_get", | ||||||
|     ) |     ) | ||||||
| @ -286,7 +382,7 @@ class FlowExecutorView(APIView): | |||||||
|                 span.set_data("authentik Stage", self.current_stage_view) |                 span.set_data("authentik Stage", self.current_stage_view) | ||||||
|                 span.set_data("authentik Flow", self.flow.slug) |                 span.set_data("authentik Flow", self.flow.slug) | ||||||
|                 stage_response = self.current_stage_view.dispatch(request) |                 stage_response = self.current_stage_view.dispatch(request) | ||||||
|                 return to_stage_response(request, stage_response) |                 return to_stage_response(request, stage_response, self.container.exec_id) | ||||||
|         except Exception as exc: |         except Exception as exc: | ||||||
|             return self.handle_exception(exc) |             return self.handle_exception(exc) | ||||||
|  |  | ||||||
| @ -305,12 +401,19 @@ class FlowExecutorView(APIView): | |||||||
|         ), |         ), | ||||||
|         parameters=[ |         parameters=[ | ||||||
|             OpenApiParameter( |             OpenApiParameter( | ||||||
|                 name="query", |                 name=QS_QUERY, | ||||||
|                 location=OpenApiParameter.QUERY, |                 location=OpenApiParameter.QUERY, | ||||||
|                 required=True, |                 required=True, | ||||||
|                 description="Querystring as received", |                 description="Querystring as received", | ||||||
|                 type=OpenApiTypes.STR, |                 type=OpenApiTypes.STR, | ||||||
|             ) |             ), | ||||||
|  |             OpenApiParameter( | ||||||
|  |                 name=QS_EXEC_ID, | ||||||
|  |                 location=OpenApiParameter.QUERY, | ||||||
|  |                 required=True, | ||||||
|  |                 description="Flow execution ID", | ||||||
|  |                 type=OpenApiTypes.STR, | ||||||
|  |             ), | ||||||
|         ], |         ], | ||||||
|         operation_id="flows_executor_solve", |         operation_id="flows_executor_solve", | ||||||
|     ) |     ) | ||||||
| @ -337,14 +440,15 @@ class FlowExecutorView(APIView): | |||||||
|                 span.set_data("authentik Stage", self.current_stage_view) |                 span.set_data("authentik Stage", self.current_stage_view) | ||||||
|                 span.set_data("authentik Flow", self.flow.slug) |                 span.set_data("authentik Flow", self.flow.slug) | ||||||
|                 stage_response = self.current_stage_view.dispatch(request) |                 stage_response = self.current_stage_view.dispatch(request) | ||||||
|                 return to_stage_response(request, stage_response) |                 return to_stage_response(request, stage_response, self.container.exec_id) | ||||||
|         except Exception as exc: |         except Exception as exc: | ||||||
|             return self.handle_exception(exc) |             return self.handle_exception(exc) | ||||||
|  |  | ||||||
|     def _initiate_plan(self) -> FlowPlan: |     def _initiate_plan(self) -> FlowPlan: | ||||||
|         planner = FlowPlanner(self.flow) |         planner = FlowPlanner(self.flow) | ||||||
|         plan = planner.plan(self.request) |         plan = planner.plan(self.request) | ||||||
|         self.request.session[SESSION_KEY_PLAN] = plan |         container = FlowContainer.new(self.request) | ||||||
|  |         container.plan = plan | ||||||
|         try: |         try: | ||||||
|             # Call the has_stages getter to check that |             # Call the has_stages getter to check that | ||||||
|             # there are no issues with the class we might've gotten |             # there are no issues with the class we might've gotten | ||||||
| @ -368,7 +472,7 @@ class FlowExecutorView(APIView): | |||||||
|         except FlowNonApplicableException as exc: |         except FlowNonApplicableException as exc: | ||||||
|             self._logger.warning("f(exec): Flow restart not applicable to current user", exc=exc) |             self._logger.warning("f(exec): Flow restart not applicable to current user", exc=exc) | ||||||
|             return self.handle_invalid_flow(exc) |             return self.handle_invalid_flow(exc) | ||||||
|         self.request.session[SESSION_KEY_PLAN] = plan |         self.container.plan = plan | ||||||
|         kwargs = self.kwargs |         kwargs = self.kwargs | ||||||
|         kwargs.update({"flow_slug": self.flow.slug}) |         kwargs.update({"flow_slug": self.flow.slug}) | ||||||
|         return redirect_with_qs("authentik_api:flow-executor", self.request.GET, **kwargs) |         return redirect_with_qs("authentik_api:flow-executor", self.request.GET, **kwargs) | ||||||
| @ -390,9 +494,13 @@ class FlowExecutorView(APIView): | |||||||
|         ) |         ) | ||||||
|         self.cancel() |         self.cancel() | ||||||
|         if next_param and not is_url_absolute(next_param): |         if next_param and not is_url_absolute(next_param): | ||||||
|             return to_stage_response(self.request, redirect_with_qs(next_param)) |             return to_stage_response( | ||||||
|  |                 self.request, redirect_with_qs(next_param), self.container.exec_id | ||||||
|  |             ) | ||||||
|         return to_stage_response( |         return to_stage_response( | ||||||
|             self.request, self.stage_invalid(error_message=_("Invalid next URL")) |             self.request, | ||||||
|  |             self.stage_invalid(error_message=_("Invalid next URL")), | ||||||
|  |             self.container.exec_id, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|     def stage_ok(self) -> HttpResponse: |     def stage_ok(self) -> HttpResponse: | ||||||
| @ -406,7 +514,7 @@ class FlowExecutorView(APIView): | |||||||
|             self.current_stage_view.cleanup() |             self.current_stage_view.cleanup() | ||||||
|         self.request.session.get(SESSION_KEY_HISTORY, []).append(deepcopy(self.plan)) |         self.request.session.get(SESSION_KEY_HISTORY, []).append(deepcopy(self.plan)) | ||||||
|         self.plan.pop() |         self.plan.pop() | ||||||
|         self.request.session[SESSION_KEY_PLAN] = self.plan |         self.container.plan = self.plan | ||||||
|         if self.plan.bindings: |         if self.plan.bindings: | ||||||
|             self._logger.debug( |             self._logger.debug( | ||||||
|                 "f(exec): Continuing with next stage", |                 "f(exec): Continuing with next stage", | ||||||
| @ -449,6 +557,7 @@ class FlowExecutorView(APIView): | |||||||
|  |  | ||||||
|     def cancel(self): |     def cancel(self): | ||||||
|         """Cancel current flow execution""" |         """Cancel current flow execution""" | ||||||
|  |         # TODO: Clean up container | ||||||
|         keys_to_delete = [ |         keys_to_delete = [ | ||||||
|             SESSION_KEY_APPLICATION_PRE, |             SESSION_KEY_APPLICATION_PRE, | ||||||
|             SESSION_KEY_PLAN, |             SESSION_KEY_PLAN, | ||||||
| @ -471,8 +580,8 @@ class CancelView(View): | |||||||
|  |  | ||||||
|     def get(self, request: HttpRequest) -> HttpResponse: |     def get(self, request: HttpRequest) -> HttpResponse: | ||||||
|         """View which canels the currently active plan""" |         """View which canels the currently active plan""" | ||||||
|         if SESSION_KEY_PLAN in request.session: |         if FlowContainer(request, request.GET.get(QS_EXEC_ID)).exists(): | ||||||
|             del request.session[SESSION_KEY_PLAN] |             del request.session[SESSION_KEY_PLAN_CONTAINER % request.GET.get(QS_EXEC_ID)] | ||||||
|             LOGGER.debug("Canceled current plan") |             LOGGER.debug("Canceled current plan") | ||||||
|         return redirect("authentik_flows:default-invalidation") |         return redirect("authentik_flows:default-invalidation") | ||||||
|  |  | ||||||
| @ -520,19 +629,12 @@ class ToDefaultFlow(View): | |||||||
|  |  | ||||||
|     def dispatch(self, request: HttpRequest) -> HttpResponse: |     def dispatch(self, request: HttpRequest) -> HttpResponse: | ||||||
|         flow = self.get_flow() |         flow = self.get_flow() | ||||||
|         # If user already has a pending plan, clear it so we don't have to later. |         get_qs = request.GET.copy() | ||||||
|         if SESSION_KEY_PLAN in self.request.session: |         get_qs[QS_EXEC_ID] = str(uuid4()) | ||||||
|             plan: FlowPlan = self.request.session[SESSION_KEY_PLAN] |         return redirect_with_qs("authentik_core:if-flow", get_qs, flow_slug=flow.slug) | ||||||
|             if plan.flow_pk != flow.pk.hex: |  | ||||||
|                 LOGGER.warning( |  | ||||||
|                     "f(def): Found existing plan for other flow, deleting plan", |  | ||||||
|                     flow_slug=flow.slug, |  | ||||||
|                 ) |  | ||||||
|                 del self.request.session[SESSION_KEY_PLAN] |  | ||||||
|         return redirect_with_qs("authentik_core:if-flow", request.GET, flow_slug=flow.slug) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def to_stage_response(request: HttpRequest, source: HttpResponse) -> HttpResponse: | def to_stage_response(request: HttpRequest, source: HttpResponse, xid: str) -> HttpResponse: | ||||||
|     """Convert normal HttpResponse into JSON Response""" |     """Convert normal HttpResponse into JSON Response""" | ||||||
|     if ( |     if ( | ||||||
|         isinstance(source, HttpResponseRedirect) |         isinstance(source, HttpResponseRedirect) | ||||||
| @ -551,6 +653,7 @@ def to_stage_response(request: HttpRequest, source: HttpResponse) -> HttpRespons | |||||||
|             RedirectChallenge( |             RedirectChallenge( | ||||||
|                 { |                 { | ||||||
|                     "to": str(redirect_url), |                     "to": str(redirect_url), | ||||||
|  |                     "xid": xid, | ||||||
|                 } |                 } | ||||||
|             ) |             ) | ||||||
|         ) |         ) | ||||||
| @ -559,6 +662,7 @@ def to_stage_response(request: HttpRequest, source: HttpResponse) -> HttpRespons | |||||||
|             ShellChallenge( |             ShellChallenge( | ||||||
|                 { |                 { | ||||||
|                     "body": source.render().content.decode("utf-8"), |                     "body": source.render().content.decode("utf-8"), | ||||||
|  |                     "xid": xid, | ||||||
|                 } |                 } | ||||||
|             ) |             ) | ||||||
|         ) |         ) | ||||||
| @ -568,6 +672,7 @@ def to_stage_response(request: HttpRequest, source: HttpResponse) -> HttpRespons | |||||||
|             ShellChallenge( |             ShellChallenge( | ||||||
|                 { |                 { | ||||||
|                     "body": source.content.decode("utf-8"), |                     "body": source.content.decode("utf-8"), | ||||||
|  |                     "xid": xid, | ||||||
|                 } |                 } | ||||||
|             ) |             ) | ||||||
|         ) |         ) | ||||||
| @ -599,4 +704,6 @@ class ConfigureFlowInitView(LoginRequiredMixin, View): | |||||||
|         except FlowNonApplicableException: |         except FlowNonApplicableException: | ||||||
|             LOGGER.warning("Flow not applicable to user") |             LOGGER.warning("Flow not applicable to user") | ||||||
|             raise Http404 from None |             raise Http404 from None | ||||||
|         return plan.to_redirect(request, stage.configure_flow) |         container = FlowContainer.new(request) | ||||||
|  |         container.plan = plan | ||||||
|  |         return container.to_redirect(request, stage.configure_flow) | ||||||
|  | |||||||
| @ -7,6 +7,7 @@ from ua_parser.user_agent_parser import Parse | |||||||
|  |  | ||||||
| from authentik.core.views.interface import InterfaceView | from authentik.core.views.interface import InterfaceView | ||||||
| from authentik.flows.models import Flow | from authentik.flows.models import Flow | ||||||
|  | from authentik.flows.views.executor import QS_EXEC_ID | ||||||
|  |  | ||||||
|  |  | ||||||
| class FlowInterfaceView(InterfaceView): | class FlowInterfaceView(InterfaceView): | ||||||
| @ -15,6 +16,7 @@ class FlowInterfaceView(InterfaceView): | |||||||
|     def get_context_data(self, **kwargs: Any) -> dict[str, Any]: |     def get_context_data(self, **kwargs: Any) -> dict[str, Any]: | ||||||
|         kwargs["flow"] = get_object_or_404(Flow, slug=self.kwargs.get("flow_slug")) |         kwargs["flow"] = get_object_or_404(Flow, slug=self.kwargs.get("flow_slug")) | ||||||
|         kwargs["inspector"] = "inspector" in self.request.GET |         kwargs["inspector"] = "inspector" in self.request.GET | ||||||
|  |         kwargs["xid"] = self.request.GET.get(QS_EXEC_ID) | ||||||
|         return super().get_context_data(**kwargs) |         return super().get_context_data(**kwargs) | ||||||
|  |  | ||||||
|     def compat_needs_sfe(self) -> bool: |     def compat_needs_sfe(self) -> bool: | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
									
									
									
									
								
							| @ -82,3 +82,5 @@ require ( | |||||||
| 	google.golang.org/protobuf v1.36.1 // indirect | 	google.golang.org/protobuf v1.36.1 // indirect | ||||||
| 	gopkg.in/yaml.v3 v3.0.1 // indirect | 	gopkg.in/yaml.v3 v3.0.1 // indirect | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | replace goauthentik.io/api/v3 => ./gen-go-api | ||||||
|  | |||||||
							
								
								
									
										92
									
								
								schema.yml
									
									
									
									
									
								
							
							
						
						
									
										92
									
								
								schema.yml
									
									
									
									
									
								
							| @ -8917,6 +8917,11 @@ paths: | |||||||
|           type: string |           type: string | ||||||
|         description: Querystring as received |         description: Querystring as received | ||||||
|         required: true |         required: true | ||||||
|  |       - in: query | ||||||
|  |         name: xid | ||||||
|  |         schema: | ||||||
|  |           type: string | ||||||
|  |         description: Flow execution ID | ||||||
|       tags: |       tags: | ||||||
|       - flows |       - flows | ||||||
|       security: |       security: | ||||||
| @ -8957,6 +8962,12 @@ paths: | |||||||
|           type: string |           type: string | ||||||
|         description: Querystring as received |         description: Querystring as received | ||||||
|         required: true |         required: true | ||||||
|  |       - in: query | ||||||
|  |         name: xid | ||||||
|  |         schema: | ||||||
|  |           type: string | ||||||
|  |         description: Flow execution ID | ||||||
|  |         required: true | ||||||
|       tags: |       tags: | ||||||
|       - flows |       - flows | ||||||
|       requestBody: |       requestBody: | ||||||
| @ -39437,6 +39448,8 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: ak-stage-access-denied |           default: ak-stage-access-denied | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
| @ -39452,6 +39465,7 @@ components: | |||||||
|       required: |       required: | ||||||
|       - pending_user |       - pending_user | ||||||
|       - pending_user_avatar |       - pending_user_avatar | ||||||
|  |       - xid | ||||||
|     AlgEnum: |     AlgEnum: | ||||||
|       enum: |       enum: | ||||||
|       - rsa |       - rsa | ||||||
| @ -39551,6 +39565,8 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: ak-source-oauth-apple |           default: ak-source-oauth-apple | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
| @ -39570,6 +39586,7 @@ components: | |||||||
|       - redirect_uri |       - redirect_uri | ||||||
|       - scope |       - scope | ||||||
|       - state |       - state | ||||||
|  |       - xid | ||||||
|     Application: |     Application: | ||||||
|       type: object |       type: object | ||||||
|       description: Application Serializer |       description: Application Serializer | ||||||
| @ -39878,6 +39895,8 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: ak-stage-authenticator-duo |           default: ak-stage-authenticator-duo | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
| @ -39900,6 +39919,7 @@ components: | |||||||
|       - pending_user |       - pending_user | ||||||
|       - pending_user_avatar |       - pending_user_avatar | ||||||
|       - stage_uuid |       - stage_uuid | ||||||
|  |       - xid | ||||||
|     AuthenticatorDuoChallengeResponseRequest: |     AuthenticatorDuoChallengeResponseRequest: | ||||||
|       type: object |       type: object | ||||||
|       description: Pseudo class for duo response |       description: Pseudo class for duo response | ||||||
| @ -40037,6 +40057,8 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: ak-stage-authenticator-email |           default: ak-stage-authenticator-email | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
| @ -40056,6 +40078,7 @@ components: | |||||||
|       required: |       required: | ||||||
|       - pending_user |       - pending_user | ||||||
|       - pending_user_avatar |       - pending_user_avatar | ||||||
|  |       - xid | ||||||
|     AuthenticatorEmailChallengeResponseRequest: |     AuthenticatorEmailChallengeResponseRequest: | ||||||
|       type: object |       type: object | ||||||
|       description: Authenticator Email Challenge response, device is set by get_response_instance |       description: Authenticator Email Challenge response, device is set by get_response_instance | ||||||
| @ -40293,6 +40316,8 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: ak-stage-authenticator-sms |           default: ak-stage-authenticator-sms | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
| @ -40309,6 +40334,7 @@ components: | |||||||
|       required: |       required: | ||||||
|       - pending_user |       - pending_user | ||||||
|       - pending_user_avatar |       - pending_user_avatar | ||||||
|  |       - xid | ||||||
|     AuthenticatorSMSChallengeResponseRequest: |     AuthenticatorSMSChallengeResponseRequest: | ||||||
|       type: object |       type: object | ||||||
|       description: SMS Challenge response, device is set by get_response_instance |       description: SMS Challenge response, device is set by get_response_instance | ||||||
| @ -40456,6 +40482,8 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: ak-stage-authenticator-static |           default: ak-stage-authenticator-static | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
| @ -40474,6 +40502,7 @@ components: | |||||||
|       - codes |       - codes | ||||||
|       - pending_user |       - pending_user | ||||||
|       - pending_user_avatar |       - pending_user_avatar | ||||||
|  |       - xid | ||||||
|     AuthenticatorStaticChallengeResponseRequest: |     AuthenticatorStaticChallengeResponseRequest: | ||||||
|       type: object |       type: object | ||||||
|       description: Pseudo class for static response |       description: Pseudo class for static response | ||||||
| @ -40577,6 +40606,8 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: ak-stage-authenticator-totp |           default: ak-stage-authenticator-totp | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
| @ -40593,6 +40624,7 @@ components: | |||||||
|       - config_url |       - config_url | ||||||
|       - pending_user |       - pending_user | ||||||
|       - pending_user_avatar |       - pending_user_avatar | ||||||
|  |       - xid | ||||||
|     AuthenticatorTOTPChallengeResponseRequest: |     AuthenticatorTOTPChallengeResponseRequest: | ||||||
|       type: object |       type: object | ||||||
|       description: TOTP Challenge response, device is set by get_response_instance |       description: TOTP Challenge response, device is set by get_response_instance | ||||||
| @ -40804,6 +40836,8 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: ak-stage-authenticator-validate |           default: ak-stage-authenticator-validate | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
| @ -40827,6 +40861,7 @@ components: | |||||||
|       - device_challenges |       - device_challenges | ||||||
|       - pending_user |       - pending_user | ||||||
|       - pending_user_avatar |       - pending_user_avatar | ||||||
|  |       - xid | ||||||
|     AuthenticatorValidationChallengeResponseRequest: |     AuthenticatorValidationChallengeResponseRequest: | ||||||
|       type: object |       type: object | ||||||
|       description: Challenge used for Code-based and WebAuthn authenticators |       description: Challenge used for Code-based and WebAuthn authenticators | ||||||
| @ -40857,6 +40892,8 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: ak-stage-authenticator-webauthn |           default: ak-stage-authenticator-webauthn | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
| @ -40874,6 +40911,7 @@ components: | |||||||
|       - pending_user |       - pending_user | ||||||
|       - pending_user_avatar |       - pending_user_avatar | ||||||
|       - registration |       - registration | ||||||
|  |       - xid | ||||||
|     AuthenticatorWebAuthnChallengeResponseRequest: |     AuthenticatorWebAuthnChallengeResponseRequest: | ||||||
|       type: object |       type: object | ||||||
|       description: WebAuthn Challenge response |       description: WebAuthn Challenge response | ||||||
| @ -41006,6 +41044,8 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: ak-stage-autosubmit |           default: ak-stage-autosubmit | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
| @ -41023,6 +41063,7 @@ components: | |||||||
|       required: |       required: | ||||||
|       - attrs |       - attrs | ||||||
|       - url |       - url | ||||||
|  |       - xid | ||||||
|     BackendsEnum: |     BackendsEnum: | ||||||
|       enum: |       enum: | ||||||
|       - authentik.core.auth.InbuiltBackend |       - authentik.core.auth.InbuiltBackend | ||||||
| @ -41269,6 +41310,8 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: ak-stage-captcha |           default: ak-stage-captcha | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
| @ -41291,6 +41334,7 @@ components: | |||||||
|       - pending_user |       - pending_user | ||||||
|       - pending_user_avatar |       - pending_user_avatar | ||||||
|       - site_key |       - site_key | ||||||
|  |       - xid | ||||||
|     CaptchaChallengeResponseRequest: |     CaptchaChallengeResponseRequest: | ||||||
|       type: object |       type: object | ||||||
|       description: Validate captcha token |       description: Validate captcha token | ||||||
| @ -41674,6 +41718,8 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: ak-stage-consent |           default: ak-stage-consent | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
| @ -41702,6 +41748,7 @@ components: | |||||||
|       - pending_user_avatar |       - pending_user_avatar | ||||||
|       - permissions |       - permissions | ||||||
|       - token |       - token | ||||||
|  |       - xid | ||||||
|     ConsentChallengeResponseRequest: |     ConsentChallengeResponseRequest: | ||||||
|       type: object |       type: object | ||||||
|       description: Consent challenge response, any valid response request is valid |       description: Consent challenge response, any valid response request is valid | ||||||
| @ -42475,6 +42522,8 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: ak-stage-dummy |           default: ak-stage-dummy | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
| @ -42485,6 +42534,7 @@ components: | |||||||
|           type: string |           type: string | ||||||
|       required: |       required: | ||||||
|       - name |       - name | ||||||
|  |       - xid | ||||||
|     DummyChallengeResponseRequest: |     DummyChallengeResponseRequest: | ||||||
|       type: object |       type: object | ||||||
|       description: Dummy challenge response |       description: Dummy challenge response | ||||||
| @ -42677,12 +42727,16 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: ak-stage-email |           default: ak-stage-email | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
|             type: array |             type: array | ||||||
|             items: |             items: | ||||||
|               $ref: '#/components/schemas/ErrorDetail' |               $ref: '#/components/schemas/ErrorDetail' | ||||||
|  |       required: | ||||||
|  |       - xid | ||||||
|     EmailChallengeResponseRequest: |     EmailChallengeResponseRequest: | ||||||
|       type: object |       type: object | ||||||
|       description: |- |       description: |- | ||||||
| @ -43601,6 +43655,8 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: ak-stage-flow-error |           default: ak-stage-flow-error | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
| @ -43615,6 +43671,7 @@ components: | |||||||
|           type: string |           type: string | ||||||
|       required: |       required: | ||||||
|       - request_id |       - request_id | ||||||
|  |       - xid | ||||||
|     FlowImportResult: |     FlowImportResult: | ||||||
|       type: object |       type: object | ||||||
|       description: Logs of an attempted flow import |       description: Logs of an attempted flow import | ||||||
| @ -43929,6 +43986,8 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: xak-flow-frame |           default: xak-flow-frame | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
| @ -43945,6 +44004,7 @@ components: | |||||||
|       required: |       required: | ||||||
|       - loading_text |       - loading_text | ||||||
|       - url |       - url | ||||||
|  |       - xid | ||||||
|     FrameChallengeResponseRequest: |     FrameChallengeResponseRequest: | ||||||
|       type: object |       type: object | ||||||
|       description: Base class for all challenge responses |       description: Base class for all challenge responses | ||||||
| @ -44747,6 +44807,8 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: ak-stage-identification |           default: ak-stage-identification | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
| @ -44791,6 +44853,7 @@ components: | |||||||
|       - primary_action |       - primary_action | ||||||
|       - show_source_labels |       - show_source_labels | ||||||
|       - user_fields |       - user_fields | ||||||
|  |       - xid | ||||||
|     IdentificationChallengeResponseRequest: |     IdentificationChallengeResponseRequest: | ||||||
|       type: object |       type: object | ||||||
|       description: Identification challenge |       description: Identification challenge | ||||||
| @ -47233,12 +47296,16 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: ak-provider-oauth2-device-code |           default: ak-provider-oauth2-device-code | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
|             type: array |             type: array | ||||||
|             items: |             items: | ||||||
|               $ref: '#/components/schemas/ErrorDetail' |               $ref: '#/components/schemas/ErrorDetail' | ||||||
|  |       required: | ||||||
|  |       - xid | ||||||
|     OAuthDeviceCodeChallengeResponseRequest: |     OAuthDeviceCodeChallengeResponseRequest: | ||||||
|       type: object |       type: object | ||||||
|       description: Response that includes the user-entered device code |       description: Response that includes the user-entered device code | ||||||
| @ -47261,12 +47328,16 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: ak-provider-oauth2-device-code-finish |           default: ak-provider-oauth2-device-code-finish | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
|             type: array |             type: array | ||||||
|             items: |             items: | ||||||
|               $ref: '#/components/schemas/ErrorDetail' |               $ref: '#/components/schemas/ErrorDetail' | ||||||
|  |       required: | ||||||
|  |       - xid | ||||||
|     OAuthDeviceCodeFinishChallengeResponseRequest: |     OAuthDeviceCodeFinishChallengeResponseRequest: | ||||||
|       type: object |       type: object | ||||||
|       description: Response that device has been authenticated and tab can be closed |       description: Response that device has been authenticated and tab can be closed | ||||||
| @ -49411,6 +49482,8 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: ak-stage-password |           default: ak-stage-password | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
| @ -49429,6 +49502,7 @@ components: | |||||||
|       required: |       required: | ||||||
|       - pending_user |       - pending_user | ||||||
|       - pending_user_avatar |       - pending_user_avatar | ||||||
|  |       - xid | ||||||
|     PasswordChallengeResponseRequest: |     PasswordChallengeResponseRequest: | ||||||
|       type: object |       type: object | ||||||
|       description: Password challenge response |       description: Password challenge response | ||||||
| @ -52990,6 +53064,8 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: ak-source-plex |           default: ak-source-plex | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
| @ -53003,6 +53079,7 @@ components: | |||||||
|       required: |       required: | ||||||
|       - client_id |       - client_id | ||||||
|       - slug |       - slug | ||||||
|  |       - xid | ||||||
|     PlexAuthenticationChallengeResponseRequest: |     PlexAuthenticationChallengeResponseRequest: | ||||||
|       type: object |       type: object | ||||||
|       description: Pseudo class for plex response |       description: Pseudo class for plex response | ||||||
| @ -53515,6 +53592,8 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: ak-stage-prompt |           default: ak-stage-prompt | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
| @ -53527,6 +53606,7 @@ components: | |||||||
|             $ref: '#/components/schemas/StagePrompt' |             $ref: '#/components/schemas/StagePrompt' | ||||||
|       required: |       required: | ||||||
|       - fields |       - fields | ||||||
|  |       - xid | ||||||
|     PromptChallengeResponseRequest: |     PromptChallengeResponseRequest: | ||||||
|       type: object |       type: object | ||||||
|       description: |- |       description: |- | ||||||
| @ -54711,6 +54791,8 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: xak-flow-redirect |           default: xak-flow-redirect | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
| @ -54721,6 +54803,7 @@ components: | |||||||
|           type: string |           type: string | ||||||
|       required: |       required: | ||||||
|       - to |       - to | ||||||
|  |       - xid | ||||||
|     RedirectChallengeResponseRequest: |     RedirectChallengeResponseRequest: | ||||||
|       type: object |       type: object | ||||||
|       description: Redirect challenge response |       description: Redirect challenge response | ||||||
| @ -56616,6 +56699,8 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: ak-stage-session-end |           default: ak-stage-session-end | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
| @ -56638,6 +56723,7 @@ components: | |||||||
|       - brand_name |       - brand_name | ||||||
|       - pending_user |       - pending_user | ||||||
|       - pending_user_avatar |       - pending_user_avatar | ||||||
|  |       - xid | ||||||
|     SessionUser: |     SessionUser: | ||||||
|       type: object |       type: object | ||||||
|       description: |- |       description: |- | ||||||
| @ -56750,6 +56836,8 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: xak-flow-shell |           default: xak-flow-shell | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
| @ -56760,6 +56848,7 @@ components: | |||||||
|           type: string |           type: string | ||||||
|       required: |       required: | ||||||
|       - body |       - body | ||||||
|  |       - xid | ||||||
|     SignatureAlgorithmEnum: |     SignatureAlgorithmEnum: | ||||||
|       enum: |       enum: | ||||||
|       - http://www.w3.org/2000/09/xmldsig#rsa-sha1 |       - http://www.w3.org/2000/09/xmldsig#rsa-sha1 | ||||||
| @ -58034,6 +58123,8 @@ components: | |||||||
|         component: |         component: | ||||||
|           type: string |           type: string | ||||||
|           default: ak-stage-user-login |           default: ak-stage-user-login | ||||||
|  |         xid: | ||||||
|  |           type: string | ||||||
|         response_errors: |         response_errors: | ||||||
|           type: object |           type: object | ||||||
|           additionalProperties: |           additionalProperties: | ||||||
| @ -58047,6 +58138,7 @@ components: | |||||||
|       required: |       required: | ||||||
|       - pending_user |       - pending_user | ||||||
|       - pending_user_avatar |       - pending_user_avatar | ||||||
|  |       - xid | ||||||
|     UserLoginChallengeResponseRequest: |     UserLoginChallengeResponseRequest: | ||||||
|       type: object |       type: object | ||||||
|       description: User login challenge |       description: User login challenge | ||||||
|  | |||||||
| @ -85,6 +85,9 @@ export class FlowExecutor extends Interface implements StageHost { | |||||||
|  |  | ||||||
|     ws: WebsocketClient; |     ws: WebsocketClient; | ||||||
|  |  | ||||||
|  |     @property() | ||||||
|  |     xid?: string; | ||||||
|  |  | ||||||
|     static get styles(): CSSResult[] { |     static get styles(): CSSResult[] { | ||||||
|         return [PFBase, PFLogin, PFDrawer, PFButton, PFTitle, PFList, PFBackgroundImage].concat(css` |         return [PFBase, PFLogin, PFDrawer, PFButton, PFTitle, PFList, PFBackgroundImage].concat(css` | ||||||
|             :host { |             :host { | ||||||
| @ -219,6 +222,7 @@ export class FlowExecutor extends Interface implements StageHost { | |||||||
|             const challenge = await new FlowsApi(DEFAULT_CONFIG).flowsExecutorSolve({ |             const challenge = await new FlowsApi(DEFAULT_CONFIG).flowsExecutorSolve({ | ||||||
|                 flowSlug: this.flowSlug, |                 flowSlug: this.flowSlug, | ||||||
|                 query: window.location.search.substring(1), |                 query: window.location.search.substring(1), | ||||||
|  |                 xid: this.xid || "", | ||||||
|                 flowChallengeResponseRequest: payload, |                 flowChallengeResponseRequest: payload, | ||||||
|             }); |             }); | ||||||
|             if (this.inspectorOpen) { |             if (this.inspectorOpen) { | ||||||
| @ -252,6 +256,7 @@ export class FlowExecutor extends Interface implements StageHost { | |||||||
|             const challenge = await new FlowsApi(DEFAULT_CONFIG).flowsExecutorGet({ |             const challenge = await new FlowsApi(DEFAULT_CONFIG).flowsExecutorGet({ | ||||||
|                 flowSlug: this.flowSlug, |                 flowSlug: this.flowSlug, | ||||||
|                 query: window.location.search.substring(1), |                 query: window.location.search.substring(1), | ||||||
|  |                 xid: this.xid, | ||||||
|             }); |             }); | ||||||
|             if (this.inspectorOpen) { |             if (this.inspectorOpen) { | ||||||
|                 window.dispatchEvent( |                 window.dispatchEvent( | ||||||
| @ -262,6 +267,7 @@ export class FlowExecutor extends Interface implements StageHost { | |||||||
|                 ); |                 ); | ||||||
|             } |             } | ||||||
|             this.challenge = challenge; |             this.challenge = challenge; | ||||||
|  |             this.xid = challenge.xid ?? undefined; | ||||||
|             if (this.challenge.flowInfo) { |             if (this.challenge.flowInfo) { | ||||||
|                 this.flowInfo = this.challenge.flowInfo; |                 this.flowInfo = this.challenge.flowInfo; | ||||||
|             } |             } | ||||||
| @ -286,6 +292,7 @@ export class FlowExecutor extends Interface implements StageHost { | |||||||
|             component: "ak-stage-flow-error", |             component: "ak-stage-flow-error", | ||||||
|             error: body, |             error: body, | ||||||
|             requestId: "", |             requestId: "", | ||||||
|  |             xid: "", | ||||||
|         }; |         }; | ||||||
|         this.challenge = challenge as ChallengeTypes; |         this.challenge = challenge as ChallengeTypes; | ||||||
|     } |     } | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	