From 8db1d86c6bda29d2c437872c519849a2eb9f3b7a Mon Sep 17 00:00:00 2001 From: Jens L Date: Sat, 13 Jul 2024 18:37:29 +0200 Subject: [PATCH] flows: remove stage challenge type (#10476) * flows: remove stage challenge type Signed-off-by: Jens Langhammer * fix Signed-off-by: Jens Langhammer * improve coverage Signed-off-by: Jens Langhammer --------- Signed-off-by: Jens Langhammer --- authentik/core/views/apps.py | 2 - authentik/flows/challenge.py | 12 --- authentik/flows/stage.py | 3 - authentik/flows/tests/__init__.py | 6 +- authentik/flows/tests/test_challenges.py | 4 +- authentik/flows/tests/test_inspector.py | 2 - authentik/flows/views/executor.py | 4 - .../providers/oauth2/tests/test_authorize.py | 6 -- .../providers/oauth2/tests/test_token_pkce.py | 5 -- authentik/providers/oauth2/views/authorize.py | 2 - .../providers/oauth2/views/device_finish.py | 3 +- .../providers/oauth2/views/device_init.py | 3 +- authentik/providers/saml/views/flows.py | 2 - authentik/root/settings.py | 1 - authentik/sources/oauth/types/apple.py | 3 +- authentik/sources/oauth/types/registry.py | 3 +- authentik/sources/plex/models.py | 3 +- authentik/sources/saml/models.py | 3 +- authentik/sources/saml/views.py | 2 - authentik/stages/authenticator_duo/stage.py | 2 - authentik/stages/authenticator_sms/stage.py | 2 - .../stages/authenticator_static/stage.py | 3 +- authentik/stages/authenticator_totp/stage.py | 2 - .../stages/authenticator_validate/stage.py | 3 +- .../stages/authenticator_webauthn/stage.py | 2 - authentik/stages/captcha/stage.py | 2 - authentik/stages/consent/stage.py | 2 - authentik/stages/dummy/stage.py | 3 +- authentik/stages/email/stage.py | 3 +- authentik/stages/identification/stage.py | 2 - authentik/stages/identification/tests.py | 7 -- authentik/stages/password/stage.py | 7 +- authentik/stages/prompt/api.py | 3 +- authentik/stages/prompt/stage.py | 3 +- authentik/stages/prompt/tests.py | 2 - authentik/stages/user_login/stage.py | 8 +- authentik/stages/user_login/tests.py | 5 ++ internal/outpost/flow/const.go | 1 + internal/outpost/flow/executor.go | 26 +++---- internal/outpost/flow/executor_test.go | 13 ++++ schema.yml | 78 ------------------- web/src/flow/FlowExecutor.ts | 28 ++----- .../AccessDeniedStage.stories.ts | 3 +- .../AuthenticatorTOTPStage.stories.ts | 3 +- .../stages/captcha/CaptchaStage.stories.ts | 5 +- .../details/UserSettingsFlowExecutor.ts | 43 ++++------ 46 files changed, 75 insertions(+), 255 deletions(-) create mode 100644 internal/outpost/flow/executor_test.go diff --git a/authentik/core/views/apps.py b/authentik/core/views/apps.py index 9843cd1257..d43118f649 100644 --- a/authentik/core/views/apps.py +++ b/authentik/core/views/apps.py @@ -8,7 +8,6 @@ from django.views import View from authentik.core.models import Application from authentik.flows.challenge import ( ChallengeResponse, - ChallengeTypes, HttpChallengeResponse, RedirectChallenge, ) @@ -74,7 +73,6 @@ class RedirectToAppStage(ChallengeStageView): raise Http404 return RedirectChallenge( instance={ - "type": ChallengeTypes.REDIRECT.value, "to": launch, } ) diff --git a/authentik/flows/challenge.py b/authentik/flows/challenge.py index 03d6b5b819..ddb1d5f196 100644 --- a/authentik/flows/challenge.py +++ b/authentik/flows/challenge.py @@ -32,14 +32,6 @@ class FlowLayout(models.TextChoices): SIDEBAR_RIGHT = "sidebar_right" -class ChallengeTypes(Enum): - """Currently defined challenge types""" - - NATIVE = "native" - SHELL = "shell" - REDIRECT = "redirect" - - class ErrorDetailSerializer(PassiveSerializer): """Serializer for rest_framework's error messages""" @@ -60,9 +52,6 @@ class Challenge(PassiveSerializer): """Challenge that gets sent to the client based on which stage is currently active""" - type = ChoiceField( - choices=[(x.value, x.name) for x in ChallengeTypes], - ) flow_info = ContextualFlowInfo(required=False) component = CharField(default="") @@ -96,7 +85,6 @@ class FlowErrorChallenge(Challenge): """Challenge class when an unhandled error occurs during a stage. Normal users are shown an error message, superusers are shown a full stacktrace.""" - type = CharField(default=ChallengeTypes.NATIVE.value) component = CharField(default="ak-stage-flow-error") request_id = CharField() diff --git a/authentik/flows/stage.py b/authentik/flows/stage.py index b12838e96d..828bb9a585 100644 --- a/authentik/flows/stage.py +++ b/authentik/flows/stage.py @@ -18,7 +18,6 @@ from authentik.flows.challenge import ( AccessDeniedChallenge, Challenge, ChallengeResponse, - ChallengeTypes, ContextualFlowInfo, HttpChallengeResponse, RedirectChallenge, @@ -244,7 +243,6 @@ class AccessDeniedChallengeView(ChallengeStageView): return AccessDeniedChallenge( data={ "error_message": str(self.error_message or "Unknown error"), - "type": ChallengeTypes.NATIVE.value, "component": "ak-stage-access-denied", } ) @@ -264,7 +262,6 @@ class RedirectStage(ChallengeStageView): ) return RedirectChallenge( data={ - "type": ChallengeTypes.REDIRECT.value, "to": destination, } ) diff --git a/authentik/flows/tests/__init__.py b/authentik/flows/tests/__init__.py index f846563b04..eb0fa90652 100644 --- a/authentik/flows/tests/__init__.py +++ b/authentik/flows/tests/__init__.py @@ -8,7 +8,6 @@ from django.urls.base import reverse from rest_framework.test import APITestCase from authentik.core.models import User -from authentik.flows.challenge import ChallengeTypes from authentik.flows.models import Flow @@ -26,7 +25,6 @@ class FlowTestCase(APITestCase): self.assertEqual(response.status_code, 200) raw_response = loads(response.content.decode()) self.assertIsNotNone(raw_response["component"]) - self.assertIsNotNone(raw_response["type"]) if flow: self.assertIn("flow_info", raw_response) self.assertEqual(raw_response["flow_info"]["background"], flow.background_url) @@ -46,6 +44,4 @@ class FlowTestCase(APITestCase): def assertStageRedirects(self, response: HttpResponse, to: str) -> dict[str, Any]: """Wrapper around assertStageResponse that checks for a redirect""" - return self.assertStageResponse( - response, component="xak-flow-redirect", to=to, type=ChallengeTypes.REDIRECT.value - ) + return self.assertStageResponse(response, component="xak-flow-redirect", to=to) diff --git a/authentik/flows/tests/test_challenges.py b/authentik/flows/tests/test_challenges.py index fe1a6c288f..6b71e56b79 100644 --- a/authentik/flows/tests/test_challenges.py +++ b/authentik/flows/tests/test_challenges.py @@ -2,7 +2,7 @@ from django.test import TestCase -from authentik.flows.challenge import AutosubmitChallenge, ChallengeTypes +from authentik.flows.challenge import AutosubmitChallenge class TestChallenges(TestCase): @@ -12,7 +12,6 @@ class TestChallenges(TestCase): """Test blank autosubmit""" challenge = AutosubmitChallenge( data={ - "type": ChallengeTypes.NATIVE.value, "url": "http://localhost", "attrs": {}, } @@ -21,7 +20,6 @@ class TestChallenges(TestCase): # Test with an empty value challenge = AutosubmitChallenge( data={ - "type": ChallengeTypes.NATIVE.value, "url": "http://localhost", "attrs": {"foo": ""}, } diff --git a/authentik/flows/tests/test_inspector.py b/authentik/flows/tests/test_inspector.py index a12054fd37..59ca809066 100644 --- a/authentik/flows/tests/test_inspector.py +++ b/authentik/flows/tests/test_inspector.py @@ -7,7 +7,6 @@ from django.urls.base import reverse from rest_framework.test import APITestCase from authentik.core.tests.utils import create_test_admin_user, create_test_flow -from authentik.flows.challenge import ChallengeTypes from authentik.flows.models import FlowDesignation, FlowStageBinding, InvalidResponseAction from authentik.stages.dummy.models import DummyStage from authentik.stages.identification.models import IdentificationStage, UserFields @@ -54,7 +53,6 @@ class TestFlowInspector(APITestCase): "layout": "stacked", }, "flow_designation": "authentication", - "type": ChallengeTypes.NATIVE.value, "password_fields": False, "primary_action": "Log in", "sources": [], diff --git a/authentik/flows/views/executor.py b/authentik/flows/views/executor.py index 774206c9d3..df1e674fa3 100644 --- a/authentik/flows/views/executor.py +++ b/authentik/flows/views/executor.py @@ -30,7 +30,6 @@ from authentik.flows.apps import HIST_FLOW_EXECUTION_STAGE_TIME from authentik.flows.challenge import ( Challenge, ChallengeResponse, - ChallengeTypes, FlowErrorChallenge, HttpChallengeResponse, RedirectChallenge, @@ -552,7 +551,6 @@ def to_stage_response(request: HttpRequest, source: HttpResponse) -> HttpRespons return HttpChallengeResponse( RedirectChallenge( { - "type": ChallengeTypes.REDIRECT, "to": str(redirect_url), } ) @@ -561,7 +559,6 @@ def to_stage_response(request: HttpRequest, source: HttpResponse) -> HttpRespons return HttpChallengeResponse( ShellChallenge( { - "type": ChallengeTypes.SHELL, "body": source.render().content.decode("utf-8"), } ) @@ -571,7 +568,6 @@ def to_stage_response(request: HttpRequest, source: HttpResponse) -> HttpRespons return HttpChallengeResponse( ShellChallenge( { - "type": ChallengeTypes.SHELL, "body": source.content.decode("utf-8"), } ) diff --git a/authentik/providers/oauth2/tests/test_authorize.py b/authentik/providers/oauth2/tests/test_authorize.py index 36da518536..c3d18d0e31 100644 --- a/authentik/providers/oauth2/tests/test_authorize.py +++ b/authentik/providers/oauth2/tests/test_authorize.py @@ -10,7 +10,6 @@ from authentik.blueprints.tests import apply_blueprint from authentik.core.models import Application from authentik.core.tests.utils import create_test_admin_user, create_test_flow from authentik.events.models import Event, EventAction -from authentik.flows.challenge import ChallengeTypes from authentik.lib.generators import generate_id from authentik.lib.utils.time import timedelta_from_string from authentik.providers.oauth2.constants import TOKEN_TYPE @@ -327,7 +326,6 @@ class TestAuthorize(OAuthTestCase): response.content.decode(), { "component": "xak-flow-redirect", - "type": ChallengeTypes.REDIRECT.value, "to": f"foo://localhost?code={code.code}&state={state}", }, ) @@ -397,7 +395,6 @@ class TestAuthorize(OAuthTestCase): response.content.decode(), { "component": "xak-flow-redirect", - "type": ChallengeTypes.REDIRECT.value, "to": ( f"http://localhost#access_token={token.token}" f"&id_token={provider.encode(token.id_token.to_dict())}" @@ -460,7 +457,6 @@ class TestAuthorize(OAuthTestCase): response.content.decode(), { "component": "xak-flow-redirect", - "type": ChallengeTypes.REDIRECT.value, "to": (f"http://localhost#code={code.code}" f"&state={state}"), }, ) @@ -516,7 +512,6 @@ class TestAuthorize(OAuthTestCase): response.content.decode(), { "component": "ak-stage-autosubmit", - "type": ChallengeTypes.NATIVE.value, "url": "http://localhost", "title": f"Redirecting to {app.name}...", "attrs": { @@ -564,7 +559,6 @@ class TestAuthorize(OAuthTestCase): response.content.decode(), { "component": "ak-stage-autosubmit", - "type": ChallengeTypes.NATIVE.value, "url": "http://localhost", "title": f"Redirecting to {app.name}...", "attrs": { diff --git a/authentik/providers/oauth2/tests/test_token_pkce.py b/authentik/providers/oauth2/tests/test_token_pkce.py index f892ee4bd8..1f64476a9e 100644 --- a/authentik/providers/oauth2/tests/test_token_pkce.py +++ b/authentik/providers/oauth2/tests/test_token_pkce.py @@ -8,7 +8,6 @@ from django.urls import reverse from authentik.core.models import Application from authentik.core.tests.utils import create_test_admin_user, create_test_flow -from authentik.flows.challenge import ChallengeTypes from authentik.lib.generators import generate_id from authentik.providers.oauth2.constants import GRANT_TYPE_AUTHORIZATION_CODE from authentik.providers.oauth2.models import AuthorizationCode, OAuth2Provider @@ -60,7 +59,6 @@ class TestTokenPKCE(OAuthTestCase): response.content.decode(), { "component": "xak-flow-redirect", - "type": ChallengeTypes.REDIRECT.value, "to": f"foo://localhost?code={code.code}&state={state}", }, ) @@ -123,7 +121,6 @@ class TestTokenPKCE(OAuthTestCase): response.content.decode(), { "component": "xak-flow-redirect", - "type": ChallengeTypes.REDIRECT.value, "to": f"foo://localhost?code={code.code}&state={state}", }, ) @@ -191,7 +188,6 @@ class TestTokenPKCE(OAuthTestCase): response.content.decode(), { "component": "xak-flow-redirect", - "type": ChallengeTypes.REDIRECT.value, "to": f"foo://localhost?code={code.code}&state={state}", }, ) @@ -242,7 +238,6 @@ class TestTokenPKCE(OAuthTestCase): response.content.decode(), { "component": "xak-flow-redirect", - "type": ChallengeTypes.REDIRECT.value, "to": f"foo://localhost?code={code.code}&state={state}", }, ) diff --git a/authentik/providers/oauth2/views/authorize.py b/authentik/providers/oauth2/views/authorize.py index c660f9c58d..5cf5145c03 100644 --- a/authentik/providers/oauth2/views/authorize.py +++ b/authentik/providers/oauth2/views/authorize.py @@ -22,7 +22,6 @@ from authentik.events.signals import get_login_event from authentik.flows.challenge import ( PLAN_CONTEXT_TITLE, AutosubmitChallenge, - ChallengeTypes, HttpChallengeResponse, ) from authentik.flows.exceptions import FlowNonApplicableException @@ -484,7 +483,6 @@ class OAuthFulfillmentStage(StageView): challenge = AutosubmitChallenge( data={ - "type": ChallengeTypes.NATIVE.value, "component": "ak-stage-autosubmit", "title": self.executor.plan.context.get( PLAN_CONTEXT_TITLE, diff --git a/authentik/providers/oauth2/views/device_finish.py b/authentik/providers/oauth2/views/device_finish.py index 61bda6ae3e..146345af99 100644 --- a/authentik/providers/oauth2/views/device_finish.py +++ b/authentik/providers/oauth2/views/device_finish.py @@ -3,7 +3,7 @@ from django.http import HttpResponse from rest_framework.fields import CharField -from authentik.flows.challenge import Challenge, ChallengeResponse, ChallengeTypes +from authentik.flows.challenge import Challenge, ChallengeResponse from authentik.flows.planner import FlowPlan from authentik.flows.stage import ChallengeStageView from authentik.flows.views.executor import SESSION_KEY_PLAN @@ -38,7 +38,6 @@ class OAuthDeviceCodeFinishStage(ChallengeStageView): token.save() return OAuthDeviceCodeFinishChallenge( data={ - "type": ChallengeTypes.NATIVE.value, "component": "ak-provider-oauth2-device-code-finish", } ) diff --git a/authentik/providers/oauth2/views/device_init.py b/authentik/providers/oauth2/views/device_init.py index ed04dabffd..ffbce26b5b 100644 --- a/authentik/providers/oauth2/views/device_init.py +++ b/authentik/providers/oauth2/views/device_init.py @@ -10,7 +10,7 @@ from structlog.stdlib import get_logger from authentik.brands.models import Brand from authentik.core.models import Application -from authentik.flows.challenge import Challenge, ChallengeResponse, ChallengeTypes +from authentik.flows.challenge import Challenge, ChallengeResponse from authentik.flows.exceptions import FlowNonApplicableException from authentik.flows.models import in_memory_stage from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, PLAN_CONTEXT_SSO, FlowPlanner @@ -141,7 +141,6 @@ class OAuthDeviceCodeStage(ChallengeStageView): def get_challenge(self, *args, **kwargs) -> Challenge: return OAuthDeviceCodeChallenge( data={ - "type": ChallengeTypes.NATIVE.value, "component": "ak-provider-oauth2-device-code", } ) diff --git a/authentik/providers/saml/views/flows.py b/authentik/providers/saml/views/flows.py index afe18f8b20..5af3507bf2 100644 --- a/authentik/providers/saml/views/flows.py +++ b/authentik/providers/saml/views/flows.py @@ -16,7 +16,6 @@ from authentik.flows.challenge import ( AutoSubmitChallengeResponse, Challenge, ChallengeResponse, - ChallengeTypes, ) from authentik.flows.planner import PLAN_CONTEXT_APPLICATION from authentik.flows.stage import ChallengeStageView @@ -81,7 +80,6 @@ class SAMLFlowFinalView(ChallengeStageView): return super().get( self.request, **{ - "type": ChallengeTypes.NATIVE.value, "component": "ak-stage-autosubmit", "title": self.executor.plan.context.get( PLAN_CONTEXT_TITLE, diff --git a/authentik/root/settings.py b/authentik/root/settings.py index dcfeae4a2f..783cf351fe 100644 --- a/authentik/root/settings.py +++ b/authentik/root/settings.py @@ -148,7 +148,6 @@ SPECTACULAR_SETTINGS = { }, "ENUM_NAME_OVERRIDES": { "EventActions": "authentik.events.models.EventAction", - "ChallengeChoices": "authentik.flows.challenge.ChallengeTypes", "FlowDesignationEnum": "authentik.flows.models.FlowDesignation", "FlowLayoutEnum": "authentik.flows.models.FlowLayout", "PolicyEngineMode": "authentik.policies.models.PolicyEngineMode", diff --git a/authentik/sources/oauth/types/apple.py b/authentik/sources/oauth/types/apple.py index 08f3968a94..3d272b6042 100644 --- a/authentik/sources/oauth/types/apple.py +++ b/authentik/sources/oauth/types/apple.py @@ -9,7 +9,7 @@ from jwt import decode, encode from rest_framework.fields import CharField from structlog.stdlib import get_logger -from authentik.flows.challenge import Challenge, ChallengeResponse, ChallengeTypes +from authentik.flows.challenge import Challenge, ChallengeResponse from authentik.sources.oauth.clients.oauth2 import OAuth2Client from authentik.sources.oauth.models import OAuthSource from authentik.sources.oauth.types.registry import SourceType, registry @@ -130,6 +130,5 @@ class AppleType(SourceType): "scope": "name email", "redirect_uri": args["redirect_uri"], "state": args["state"], - "type": ChallengeTypes.NATIVE.value, } ) diff --git a/authentik/sources/oauth/types/registry.py b/authentik/sources/oauth/types/registry.py index acb59c69bd..7ff1c85dbe 100644 --- a/authentik/sources/oauth/types/registry.py +++ b/authentik/sources/oauth/types/registry.py @@ -8,7 +8,7 @@ from django.templatetags.static import static from django.urls.base import reverse from structlog.stdlib import get_logger -from authentik.flows.challenge import Challenge, ChallengeTypes, RedirectChallenge +from authentik.flows.challenge import Challenge, RedirectChallenge from authentik.sources.oauth.models import OAuthSource from authentik.sources.oauth.views.callback import OAuthCallback from authentik.sources.oauth.views.redirect import OAuthRedirect @@ -48,7 +48,6 @@ class SourceType: """Allow types to return custom challenges""" return RedirectChallenge( data={ - "type": ChallengeTypes.REDIRECT.value, "to": reverse( "authentik_sources_oauth:oauth-client-login", kwargs={"source_slug": source.slug}, diff --git a/authentik/sources/plex/models.py b/authentik/sources/plex/models.py index 13734cb3b3..12e5d92c47 100644 --- a/authentik/sources/plex/models.py +++ b/authentik/sources/plex/models.py @@ -10,7 +10,7 @@ from rest_framework.serializers import BaseSerializer, Serializer from authentik.core.models import Source, UserSourceConnection from authentik.core.types import UILoginButton, UserSettingSerializer -from authentik.flows.challenge import Challenge, ChallengeResponse, ChallengeTypes +from authentik.flows.challenge import Challenge, ChallengeResponse from authentik.lib.generators import generate_id @@ -71,7 +71,6 @@ class PlexSource(Source): return UILoginButton( challenge=PlexAuthenticationChallenge( data={ - "type": ChallengeTypes.NATIVE.value, "component": "ak-source-plex", "client_id": self.client_id, "slug": self.slug, diff --git a/authentik/sources/saml/models.py b/authentik/sources/saml/models.py index c4b998bf26..94179a080f 100644 --- a/authentik/sources/saml/models.py +++ b/authentik/sources/saml/models.py @@ -10,7 +10,7 @@ from rest_framework.serializers import Serializer from authentik.core.models import Source, UserSourceConnection from authentik.core.types import UILoginButton, UserSettingSerializer from authentik.crypto.models import CertificateKeyPair -from authentik.flows.challenge import ChallengeTypes, RedirectChallenge +from authentik.flows.challenge import RedirectChallenge from authentik.flows.models import Flow from authentik.lib.utils.time import timedelta_string_validator from authentik.sources.saml.processors.constants import ( @@ -204,7 +204,6 @@ class SAMLSource(Source): return UILoginButton( challenge=RedirectChallenge( data={ - "type": ChallengeTypes.REDIRECT.value, "to": reverse( "authentik_sources_saml:login", kwargs={"source_slug": self.slug}, diff --git a/authentik/sources/saml/views.py b/authentik/sources/saml/views.py index 37550d735e..0ef12eacba 100644 --- a/authentik/sources/saml/views.py +++ b/authentik/sources/saml/views.py @@ -21,7 +21,6 @@ from authentik.flows.challenge import ( AutosubmitChallenge, Challenge, ChallengeResponse, - ChallengeTypes, ) from authentik.flows.exceptions import FlowNonApplicableException from authentik.flows.models import in_memory_stage @@ -52,7 +51,6 @@ class AutosubmitStageView(ChallengeStageView): def get_challenge(self, *args, **kwargs) -> Challenge: return AutosubmitChallenge( data={ - "type": ChallengeTypes.NATIVE.value, "component": "ak-stage-autosubmit", "title": self.executor.plan.context.get(PLAN_CONTEXT_TITLE, ""), "url": self.executor.plan.context.get(PLAN_CONTEXT_URL, ""), diff --git a/authentik/stages/authenticator_duo/stage.py b/authentik/stages/authenticator_duo/stage.py index a19880fe38..06272b720b 100644 --- a/authentik/stages/authenticator_duo/stage.py +++ b/authentik/stages/authenticator_duo/stage.py @@ -8,7 +8,6 @@ from authentik.events.models import Event, EventAction from authentik.flows.challenge import ( Challenge, ChallengeResponse, - ChallengeTypes, WithUserInfoChallenge, ) from authentik.flows.stage import ChallengeStageView @@ -61,7 +60,6 @@ class AuthenticatorDuoStageView(ChallengeStageView): enroll = self.request.session[SESSION_KEY_DUO_ENROLL] return AuthenticatorDuoChallenge( data={ - "type": ChallengeTypes.NATIVE.value, "activation_barcode": enroll["activation_barcode"], "activation_code": enroll["activation_code"], "stage_uuid": str(stage.stage_uuid), diff --git a/authentik/stages/authenticator_sms/stage.py b/authentik/stages/authenticator_sms/stage.py index 159e5ede5a..17ce6ac65e 100644 --- a/authentik/stages/authenticator_sms/stage.py +++ b/authentik/stages/authenticator_sms/stage.py @@ -10,7 +10,6 @@ from rest_framework.fields import BooleanField, CharField, IntegerField from authentik.flows.challenge import ( Challenge, ChallengeResponse, - ChallengeTypes, WithUserInfoChallenge, ) from authentik.flows.stage import ChallengeStageView @@ -90,7 +89,6 @@ class AuthenticatorSMSStageView(ChallengeStageView): def get_challenge(self, *args, **kwargs) -> Challenge: return AuthenticatorSMSChallenge( data={ - "type": ChallengeTypes.NATIVE.value, "phone_number_required": self._has_phone_number() is None, } ) diff --git a/authentik/stages/authenticator_static/stage.py b/authentik/stages/authenticator_static/stage.py index ef4a808b12..face89bfd8 100644 --- a/authentik/stages/authenticator_static/stage.py +++ b/authentik/stages/authenticator_static/stage.py @@ -3,7 +3,7 @@ from django.http import HttpRequest, HttpResponse from rest_framework.fields import CharField, ListField -from authentik.flows.challenge import ChallengeResponse, ChallengeTypes, WithUserInfoChallenge +from authentik.flows.challenge import ChallengeResponse, WithUserInfoChallenge from authentik.flows.stage import ChallengeStageView from authentik.lib.generators import generate_id from authentik.stages.authenticator_static.models import ( @@ -38,7 +38,6 @@ class AuthenticatorStaticStageView(ChallengeStageView): tokens: list[StaticToken] = self.request.session[SESSION_STATIC_TOKENS] return AuthenticatorStaticChallenge( data={ - "type": ChallengeTypes.NATIVE.value, "codes": [token.token for token in tokens], } ) diff --git a/authentik/stages/authenticator_totp/stage.py b/authentik/stages/authenticator_totp/stage.py index 1a0791f785..1275fca174 100644 --- a/authentik/stages/authenticator_totp/stage.py +++ b/authentik/stages/authenticator_totp/stage.py @@ -11,7 +11,6 @@ from rest_framework.serializers import ValidationError from authentik.flows.challenge import ( Challenge, ChallengeResponse, - ChallengeTypes, WithUserInfoChallenge, ) from authentik.flows.stage import ChallengeStageView @@ -55,7 +54,6 @@ class AuthenticatorTOTPStageView(ChallengeStageView): device: TOTPDevice = self.request.session[SESSION_TOTP_DEVICE] return AuthenticatorTOTPChallenge( data={ - "type": ChallengeTypes.NATIVE.value, "config_url": device.config_url.replace( OTP_TOTP_ISSUER, quote(self.request.brand.branding_title) ), diff --git a/authentik/stages/authenticator_validate/stage.py b/authentik/stages/authenticator_validate/stage.py index 35d462208a..62b1326227 100644 --- a/authentik/stages/authenticator_validate/stage.py +++ b/authentik/stages/authenticator_validate/stage.py @@ -13,7 +13,7 @@ from rest_framework.serializers import ValidationError from authentik.core.api.utils import JSONDictField, PassiveSerializer from authentik.core.models import User from authentik.events.models import Event, EventAction -from authentik.flows.challenge import ChallengeResponse, ChallengeTypes, WithUserInfoChallenge +from authentik.flows.challenge import ChallengeResponse, WithUserInfoChallenge from authentik.flows.exceptions import FlowSkipStageException, StageInvalidException from authentik.flows.models import FlowDesignation, NotConfiguredAction, Stage from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER @@ -337,7 +337,6 @@ class AuthenticatorValidateStageView(ChallengeStageView): return AuthenticatorValidationChallenge( data={ "component": "ak-stage-authenticator-validate", - "type": ChallengeTypes.NATIVE.value, "device_challenges": challenges, "configuration_stages": stage_challenges, } diff --git a/authentik/stages/authenticator_webauthn/stage.py b/authentik/stages/authenticator_webauthn/stage.py index 02f9ad2107..7c25f0c449 100644 --- a/authentik/stages/authenticator_webauthn/stage.py +++ b/authentik/stages/authenticator_webauthn/stage.py @@ -30,7 +30,6 @@ from authentik.core.models import User from authentik.flows.challenge import ( Challenge, ChallengeResponse, - ChallengeTypes, WithUserInfoChallenge, ) from authentik.flows.stage import ChallengeStageView @@ -144,7 +143,6 @@ class AuthenticatorWebAuthnStageView(ChallengeStageView): self.request.session.save() return AuthenticatorWebAuthnChallenge( data={ - "type": ChallengeTypes.NATIVE.value, "registration": loads(options_to_json(registration_options)), } ) diff --git a/authentik/stages/captcha/stage.py b/authentik/stages/captcha/stage.py index e770119c5a..3967e6d3d3 100644 --- a/authentik/stages/captcha/stage.py +++ b/authentik/stages/captcha/stage.py @@ -9,7 +9,6 @@ from rest_framework.serializers import ValidationError from authentik.flows.challenge import ( Challenge, ChallengeResponse, - ChallengeTypes, WithUserInfoChallenge, ) from authentik.flows.stage import ChallengeStageView @@ -80,7 +79,6 @@ class CaptchaStageView(ChallengeStageView): return CaptchaChallenge( data={ "js_url": self.executor.current_stage.js_url, - "type": ChallengeTypes.NATIVE.value, "site_key": self.executor.current_stage.public_key, } ) diff --git a/authentik/stages/consent/stage.py b/authentik/stages/consent/stage.py index 7fbc9283fa..36648c899a 100644 --- a/authentik/stages/consent/stage.py +++ b/authentik/stages/consent/stage.py @@ -10,7 +10,6 @@ from authentik.core.api.utils import PassiveSerializer from authentik.flows.challenge import ( Challenge, ChallengeResponse, - ChallengeTypes, WithUserInfoChallenge, ) from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, PLAN_CONTEXT_PENDING_USER @@ -58,7 +57,6 @@ class ConsentStageView(ChallengeStageView): token = str(uuid4()) self.request.session[SESSION_KEY_CONSENT_TOKEN] = token data = { - "type": ChallengeTypes.NATIVE.value, "permissions": self.executor.plan.context.get(PLAN_CONTEXT_CONSENT_PERMISSIONS, []), "additional_permissions": self.executor.plan.context.get( PLAN_CONTEXT_CONSENT_EXTRA_PERMISSIONS, [] diff --git a/authentik/stages/dummy/stage.py b/authentik/stages/dummy/stage.py index e95c740817..a3a32ebd34 100644 --- a/authentik/stages/dummy/stage.py +++ b/authentik/stages/dummy/stage.py @@ -3,7 +3,7 @@ from django.http.response import HttpResponse from rest_framework.fields import CharField -from authentik.flows.challenge import Challenge, ChallengeResponse, ChallengeTypes +from authentik.flows.challenge import Challenge, ChallengeResponse from authentik.flows.stage import ChallengeStageView from authentik.lib.sentry import SentryIgnoredException @@ -34,7 +34,6 @@ class DummyStageView(ChallengeStageView): raise SentryIgnoredException("Test error") return DummyChallenge( data={ - "type": ChallengeTypes.NATIVE.value, "title": self.executor.current_stage.name, "name": self.executor.current_stage.name, } diff --git a/authentik/stages/email/stage.py b/authentik/stages/email/stage.py index 9a81a7a287..c8a7f7c02b 100644 --- a/authentik/stages/email/stage.py +++ b/authentik/stages/email/stage.py @@ -15,7 +15,7 @@ from rest_framework.fields import CharField from rest_framework.serializers import ValidationError from authentik.events.models import Event, EventAction -from authentik.flows.challenge import Challenge, ChallengeResponse, ChallengeTypes +from authentik.flows.challenge import Challenge, ChallengeResponse from authentik.flows.exceptions import StageInvalidException from authentik.flows.models import FlowDesignation, FlowToken from authentik.flows.planner import PLAN_CONTEXT_IS_RESTORED, PLAN_CONTEXT_PENDING_USER @@ -160,7 +160,6 @@ class EmailStageView(ChallengeStageView): def get_challenge(self) -> Challenge: challenge = EmailChallenge( data={ - "type": ChallengeTypes.NATIVE.value, "title": _("Email sent."), } ) diff --git a/authentik/stages/identification/stage.py b/authentik/stages/identification/stage.py index 8be41825d5..129cd14b9a 100644 --- a/authentik/stages/identification/stage.py +++ b/authentik/stages/identification/stage.py @@ -20,7 +20,6 @@ from authentik.events.utils import sanitize_item from authentik.flows.challenge import ( Challenge, ChallengeResponse, - ChallengeTypes, RedirectChallenge, ) from authentik.flows.models import FlowDesignation @@ -194,7 +193,6 @@ class IdentificationStageView(ChallengeStageView): current_stage: IdentificationStage = self.executor.current_stage challenge = IdentificationChallenge( data={ - "type": ChallengeTypes.NATIVE.value, "component": "ak-stage-identification", "primary_action": self.get_primary_action(), "user_fields": current_stage.user_fields, diff --git a/authentik/stages/identification/tests.py b/authentik/stages/identification/tests.py index 671d5aab6c..57ffed1283 100644 --- a/authentik/stages/identification/tests.py +++ b/authentik/stages/identification/tests.py @@ -4,7 +4,6 @@ from django.urls import reverse from rest_framework.exceptions import ValidationError from authentik.core.tests.utils import create_test_admin_user, create_test_flow -from authentik.flows.challenge import ChallengeTypes from authentik.flows.models import FlowDesignation, FlowStageBinding from authentik.flows.tests import FlowTestCase from authentik.lib.generators import generate_id @@ -90,7 +89,6 @@ class TestIdentificationStage(FlowTestCase): "challenge": { "component": "xak-flow-redirect", "to": "/source/oauth/login/test/", - "type": ChallengeTypes.REDIRECT.value, }, "icon_url": "/static/authentik/sources/default.svg", "name": "test", @@ -126,7 +124,6 @@ class TestIdentificationStage(FlowTestCase): "challenge": { "component": "xak-flow-redirect", "to": "/source/oauth/login/test/", - "type": ChallengeTypes.REDIRECT.value, }, "icon_url": "/static/authentik/sources/default.svg", "name": "test", @@ -189,7 +186,6 @@ class TestIdentificationStage(FlowTestCase): "challenge": { "component": "xak-flow-redirect", "to": "/source/oauth/login/test/", - "type": ChallengeTypes.REDIRECT.value, }, "icon_url": "/static/authentik/sources/default.svg", "name": "test", @@ -240,7 +236,6 @@ class TestIdentificationStage(FlowTestCase): "challenge": { "component": "xak-flow-redirect", "to": "/source/oauth/login/test/", - "type": ChallengeTypes.REDIRECT.value, }, } ], @@ -276,7 +271,6 @@ class TestIdentificationStage(FlowTestCase): "challenge": { "component": "xak-flow-redirect", "to": "/source/oauth/login/test/", - "type": ChallengeTypes.REDIRECT.value, }, "icon_url": "/static/authentik/sources/default.svg", "name": "test", @@ -304,7 +298,6 @@ class TestIdentificationStage(FlowTestCase): "challenge": { "component": "xak-flow-redirect", "to": "/source/oauth/login/test/", - "type": ChallengeTypes.REDIRECT.value, }, "icon_url": "/static/authentik/sources/default.svg", "name": "test", diff --git a/authentik/stages/password/stage.py b/authentik/stages/password/stage.py index 18d78383fb..03a6040ded 100644 --- a/authentik/stages/password/stage.py +++ b/authentik/stages/password/stage.py @@ -18,7 +18,6 @@ from authentik.core.signals import login_failed from authentik.flows.challenge import ( Challenge, ChallengeResponse, - ChallengeTypes, WithUserInfoChallenge, ) from authentik.flows.exceptions import StageInvalidException @@ -135,11 +134,7 @@ class PasswordStageView(ChallengeStageView): response_class = PasswordChallengeResponse def get_challenge(self) -> Challenge: - challenge = PasswordChallenge( - data={ - "type": ChallengeTypes.NATIVE.value, - } - ) + challenge = PasswordChallenge(data={}) recovery_flow = Flow.objects.filter(designation=FlowDesignation.RECOVERY) if recovery_flow.exists(): recover_url = reverse( diff --git a/authentik/stages/prompt/api.py b/authentik/stages/prompt/api.py index 5dfeac90fb..8dfe372352 100644 --- a/authentik/stages/prompt/api.py +++ b/authentik/stages/prompt/api.py @@ -11,7 +11,7 @@ from rest_framework.viewsets import ModelViewSet from authentik.core.api.used_by import UsedByMixin from authentik.core.expression.exceptions import PropertyMappingExpressionException from authentik.flows.api.stages import StageSerializer -from authentik.flows.challenge import ChallengeTypes, HttpChallengeResponse +from authentik.flows.challenge import HttpChallengeResponse from authentik.flows.planner import FlowPlan from authentik.flows.views.executor import FlowExecutorView from authentik.lib.generators import generate_id @@ -115,7 +115,6 @@ class PromptViewSet(UsedByMixin, ModelViewSet): ) challenge = PromptChallenge( data={ - "type": ChallengeTypes.NATIVE.value, "fields": fields, }, ) diff --git a/authentik/stages/prompt/stage.py b/authentik/stages/prompt/stage.py index 05fd04f84a..987a164446 100644 --- a/authentik/stages/prompt/stage.py +++ b/authentik/stages/prompt/stage.py @@ -21,7 +21,7 @@ from rest_framework.serializers import ValidationError from authentik.core.api.utils import PassiveSerializer from authentik.core.models import User -from authentik.flows.challenge import Challenge, ChallengeResponse, ChallengeTypes +from authentik.flows.challenge import Challenge, ChallengeResponse from authentik.flows.planner import FlowPlan from authentik.flows.stage import ChallengeStageView from authentik.policies.engine import PolicyEngine @@ -227,7 +227,6 @@ class PromptStageView(ChallengeStageView): serializers = self.get_prompt_challenge_fields(fields, context_prompt) challenge = PromptChallenge( data={ - "type": ChallengeTypes.NATIVE.value, "fields": serializers, }, ) diff --git a/authentik/stages/prompt/tests.py b/authentik/stages/prompt/tests.py index 564e573e8d..17453b2400 100644 --- a/authentik/stages/prompt/tests.py +++ b/authentik/stages/prompt/tests.py @@ -7,7 +7,6 @@ from django.urls import reverse from rest_framework.exceptions import ErrorDetail, ValidationError from authentik.core.tests.utils import create_test_admin_user, create_test_flow -from authentik.flows.challenge import ChallengeTypes from authentik.flows.markers import StageMarker from authentik.flows.models import FlowStageBinding from authentik.flows.planner import FlowPlan @@ -596,7 +595,6 @@ class TestPromptStage(FlowTestCase): self.assertJSONEqual( response.content.decode(), { - "type": ChallengeTypes.NATIVE.value, "component": "ak-stage-prompt", "fields": [ { diff --git a/authentik/stages/user_login/stage.py b/authentik/stages/user_login/stage.py index 7669acdb66..5f180a977c 100644 --- a/authentik/stages/user_login/stage.py +++ b/authentik/stages/user_login/stage.py @@ -10,7 +10,7 @@ from rest_framework.fields import BooleanField, CharField from authentik.core.models import AuthenticatedSession, User from authentik.events.middleware import audit_ignore -from authentik.flows.challenge import ChallengeResponse, ChallengeTypes, WithUserInfoChallenge +from authentik.flows.challenge import ChallengeResponse, WithUserInfoChallenge from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, PLAN_CONTEXT_SOURCE from authentik.flows.stage import ChallengeStageView from authentik.lib.utils.time import timedelta_from_string @@ -45,11 +45,7 @@ class UserLoginStageView(ChallengeStageView): response_class = UserLoginChallengeResponse def get_challenge(self, *args, **kwargs) -> UserLoginChallenge: - return UserLoginChallenge( - data={ - "type": ChallengeTypes.NATIVE.value, - } - ) + return UserLoginChallenge(data={}) def dispatch(self, request: HttpRequest) -> HttpResponse: """Check for remember_me, and do login""" diff --git a/authentik/stages/user_login/tests.py b/authentik/stages/user_login/tests.py index e9b02b483c..62c6fa1fac 100644 --- a/authentik/stages/user_login/tests.py +++ b/authentik/stages/user_login/tests.py @@ -129,6 +129,11 @@ class TestUserLoginStage(FlowTestCase): session[SESSION_KEY_PLAN] = plan session.save() + response = self.client.get( + reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}), + ) + self.assertStageResponse(response, component="ak-stage-user-login") + response = self.client.post( reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}), data={"remember_me": True}, diff --git a/internal/outpost/flow/const.go b/internal/outpost/flow/const.go index 26fcb2f9bc..32628be960 100644 --- a/internal/outpost/flow/const.go +++ b/internal/outpost/flow/const.go @@ -8,6 +8,7 @@ const ( StageIdentification = StageComponent("ak-stage-identification") StagePassword = StageComponent("ak-stage-password") StageUserLogin = StageComponent("ak-stage-user-login") + StageRedirect = StageComponent("xak-flow-redirect") ) const ( diff --git a/internal/outpost/flow/executor.go b/internal/outpost/flow/executor.go index d1e898308c..6cbad86f7e 100644 --- a/internal/outpost/flow/executor.go +++ b/internal/outpost/flow/executor.go @@ -110,9 +110,8 @@ func (fe *FlowExecutor) ApiClient() *api.APIClient { return fe.api } -type challengeInt interface { +type challengeCommon interface { GetComponent() string - GetType() api.ChallengeChoices GetResponseErrors() map[string][]api.ErrorDetail } @@ -181,9 +180,8 @@ func (fe *FlowExecutor) getInitialChallenge() (*api.ChallengeTypes, error) { if i == nil { return nil, errors.New("response instance was null") } - ch := i.(challengeInt) - fe.log.WithField("component", ch.GetComponent()).WithField("type", ch.GetType()).Debug("Got challenge") - gcsp.SetTag("authentik.flow.challenge", string(ch.GetType())) + ch := i.(challengeCommon) + fe.log.WithField("component", ch.GetComponent()).Debug("Got challenge") gcsp.SetTag("authentik.flow.component", ch.GetComponent()) gcsp.Finish() FlowTimingGet.With(prometheus.Labels{ @@ -201,7 +199,7 @@ func (fe *FlowExecutor) solveFlowChallenge(challenge *api.ChallengeTypes, depth if i == nil { return false, errors.New("response request instance was null") } - ch := i.(challengeInt) + ch := i.(challengeCommon) // Check for any validation errors that we might've gotten if len(ch.GetResponseErrors()) > 0 { @@ -212,13 +210,12 @@ func (fe *FlowExecutor) solveFlowChallenge(challenge *api.ChallengeTypes, depth } } - switch ch.GetType() { - case api.CHALLENGECHOICES_REDIRECT: + switch ch.GetComponent() { + case string(StageAccessDenied): + return false, nil + case string(StageRedirect): return true, nil - case api.CHALLENGECHOICES_NATIVE: - if ch.GetComponent() == string(StageAccessDenied) { - return false, nil - } + default: solver, ok := fe.solvers[StageComponent(ch.GetComponent())] if !ok { return false, fmt.Errorf("unsupported challenge type %s", ch.GetComponent()) @@ -238,9 +235,8 @@ func (fe *FlowExecutor) solveFlowChallenge(challenge *api.ChallengeTypes, depth if i == nil { return false, errors.New("response instance was null") } - ch = i.(challengeInt) - fe.log.WithField("component", ch.GetComponent()).WithField("type", ch.GetType()).Debug("Got response") - scsp.SetTag("authentik.flow.challenge", string(ch.GetType())) + ch = i.(challengeCommon) + fe.log.WithField("component", ch.GetComponent()).Debug("Got response") scsp.SetTag("authentik.flow.component", ch.GetComponent()) scsp.Finish() FlowTimingPost.With(prometheus.Labels{ diff --git a/internal/outpost/flow/executor_test.go b/internal/outpost/flow/executor_test.go new file mode 100644 index 0000000000..0e416eb26f --- /dev/null +++ b/internal/outpost/flow/executor_test.go @@ -0,0 +1,13 @@ +package flow + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "goauthentik.io/api/v3" +) + +func TestConvert(t *testing.T) { + var a challengeCommon = api.NewIdentificationChallengeWithDefaults() + assert.NotNil(t, a) +} diff --git a/schema.yml b/schema.yml index c5a45bf2d4..f459e3453e 100644 --- a/schema.yml +++ b/schema.yml @@ -32844,8 +32844,6 @@ components: type: object description: Challenge when a flow's active stage calls `stage_invalid()`. properties: - type: - $ref: '#/components/schemas/ChallengeChoices' flow_info: $ref: '#/components/schemas/ContextualFlowInfo' component: @@ -32866,7 +32864,6 @@ components: required: - pending_user - pending_user_avatar - - type AlgEnum: enum: - rsa @@ -32955,8 +32952,6 @@ components: description: Special challenge for apple-native authentication flow, which happens on the client. properties: - type: - $ref: '#/components/schemas/ChallengeChoices' flow_info: $ref: '#/components/schemas/ContextualFlowInfo' component: @@ -32981,7 +32976,6 @@ components: - redirect_uri - scope - state - - type Application: type: object description: Application Serializer @@ -33252,8 +33246,6 @@ components: type: object description: Duo Challenge properties: - type: - $ref: '#/components/schemas/ChallengeChoices' flow_info: $ref: '#/components/schemas/ContextualFlowInfo' component: @@ -33281,7 +33273,6 @@ components: - pending_user - pending_user_avatar - stage_uuid - - type AuthenticatorDuoChallengeResponseRequest: type: object description: Pseudo class for duo response @@ -33414,8 +33405,6 @@ components: type: object description: SMS Setup challenge properties: - type: - $ref: '#/components/schemas/ChallengeChoices' flow_info: $ref: '#/components/schemas/ContextualFlowInfo' component: @@ -33437,7 +33426,6 @@ components: required: - pending_user - pending_user_avatar - - type AuthenticatorSMSChallengeResponseRequest: type: object description: SMS Challenge response, device is set by get_response_instance @@ -33580,8 +33568,6 @@ components: type: object description: Static authenticator challenge properties: - type: - $ref: '#/components/schemas/ChallengeChoices' flow_info: $ref: '#/components/schemas/ContextualFlowInfo' component: @@ -33605,7 +33591,6 @@ components: - codes - pending_user - pending_user_avatar - - type AuthenticatorStaticChallengeResponseRequest: type: object description: Pseudo class for static response @@ -33704,8 +33689,6 @@ components: type: object description: TOTP Setup challenge properties: - type: - $ref: '#/components/schemas/ChallengeChoices' flow_info: $ref: '#/components/schemas/ContextualFlowInfo' component: @@ -33727,7 +33710,6 @@ components: - config_url - pending_user - pending_user_avatar - - type AuthenticatorTOTPChallengeResponseRequest: type: object description: TOTP Challenge response, device is set by get_response_instance @@ -33934,8 +33916,6 @@ components: type: object description: Authenticator challenge properties: - type: - $ref: '#/components/schemas/ChallengeChoices' flow_info: $ref: '#/components/schemas/ContextualFlowInfo' component: @@ -33964,7 +33944,6 @@ components: - device_challenges - pending_user - pending_user_avatar - - type AuthenticatorValidationChallengeResponseRequest: type: object description: Challenge used for Code-based and WebAuthn authenticators @@ -33990,8 +33969,6 @@ components: type: object description: WebAuthn Challenge properties: - type: - $ref: '#/components/schemas/ChallengeChoices' flow_info: $ref: '#/components/schemas/ContextualFlowInfo' component: @@ -34014,7 +33991,6 @@ components: - pending_user - pending_user_avatar - registration - - type AuthenticatorWebAuthnChallengeResponseRequest: type: object description: WebAuthn Challenge response @@ -34142,8 +34118,6 @@ components: type: object description: Autosubmit challenge used to send and navigate a POST request properties: - type: - $ref: '#/components/schemas/ChallengeChoices' flow_info: $ref: '#/components/schemas/ContextualFlowInfo' component: @@ -34165,7 +34139,6 @@ components: type: string required: - attrs - - type - url BackendsEnum: enum: @@ -34395,8 +34368,6 @@ components: type: object description: Site public key properties: - type: - $ref: '#/components/schemas/ChallengeChoices' flow_info: $ref: '#/components/schemas/ContextualFlowInfo' component: @@ -34421,7 +34392,6 @@ components: - pending_user - pending_user_avatar - site_key - - type CaptchaChallengeResponseRequest: type: object description: Validate captcha token @@ -34652,12 +34622,6 @@ components: required: - certificate_data - name - ChallengeChoices: - enum: - - native - - shell - - redirect - type: string ChallengeTypes: oneOf: - $ref: '#/components/schemas/AccessDeniedChallenge' @@ -34790,8 +34754,6 @@ components: type: object description: Challenge info for consent screens properties: - type: - $ref: '#/components/schemas/ChallengeChoices' flow_info: $ref: '#/components/schemas/ContextualFlowInfo' component: @@ -34825,7 +34787,6 @@ components: - pending_user_avatar - permissions - token - - type ConsentChallengeResponseRequest: type: object description: Consent challenge response, any valid response request is valid @@ -35274,8 +35235,6 @@ components: type: object description: Dummy challenge properties: - type: - $ref: '#/components/schemas/ChallengeChoices' flow_info: $ref: '#/components/schemas/ContextualFlowInfo' component: @@ -35291,7 +35250,6 @@ components: type: string required: - name - - type DummyChallengeResponseRequest: type: object description: Dummy challenge response @@ -35474,8 +35432,6 @@ components: type: object description: Email challenge properties: - type: - $ref: '#/components/schemas/ChallengeChoices' flow_info: $ref: '#/components/schemas/ContextualFlowInfo' component: @@ -35487,8 +35443,6 @@ components: type: array items: $ref: '#/components/schemas/ErrorDetail' - required: - - type EmailChallengeResponseRequest: type: object description: |- @@ -36314,9 +36268,6 @@ components: Challenge class when an unhandled error occurs during a stage. Normal users are shown an error message, superusers are shown a full stacktrace. properties: - type: - type: string - default: native flow_info: $ref: '#/components/schemas/ContextualFlowInfo' component: @@ -37098,8 +37049,6 @@ components: type: object description: Identification challenges with all UI elements properties: - type: - $ref: '#/components/schemas/ChallengeChoices' flow_info: $ref: '#/components/schemas/ContextualFlowInfo' component: @@ -37141,7 +37090,6 @@ components: - password_fields - primary_action - show_source_labels - - type - user_fields IdentificationChallengeResponseRequest: type: object @@ -39160,8 +39108,6 @@ components: type: object description: OAuth Device code challenge properties: - type: - $ref: '#/components/schemas/ChallengeChoices' flow_info: $ref: '#/components/schemas/ContextualFlowInfo' component: @@ -39173,8 +39119,6 @@ components: type: array items: $ref: '#/components/schemas/ErrorDetail' - required: - - type OAuthDeviceCodeChallengeResponseRequest: type: object description: Response that includes the user-entered device code @@ -39191,8 +39135,6 @@ components: type: object description: Final challenge after user enters their code properties: - type: - $ref: '#/components/schemas/ChallengeChoices' flow_info: $ref: '#/components/schemas/ContextualFlowInfo' component: @@ -39204,8 +39146,6 @@ components: type: array items: $ref: '#/components/schemas/ErrorDetail' - required: - - type OAuthDeviceCodeFinishChallengeResponseRequest: type: object description: Response that device has been authenticated and tab can be closed @@ -40996,8 +40936,6 @@ components: type: object description: Password challenge UI fields properties: - type: - $ref: '#/components/schemas/ChallengeChoices' flow_info: $ref: '#/components/schemas/ContextualFlowInfo' component: @@ -41018,7 +40956,6 @@ components: required: - pending_user - pending_user_avatar - - type PasswordChallengeResponseRequest: type: object description: Password challenge response @@ -43909,8 +43846,6 @@ components: type: object description: Challenge shown to the user in identification stage properties: - type: - $ref: '#/components/schemas/ChallengeChoices' flow_info: $ref: '#/components/schemas/ContextualFlowInfo' component: @@ -43929,7 +43864,6 @@ components: required: - client_id - slug - - type PlexAuthenticationChallengeResponseRequest: type: object description: Pseudo class for plex response @@ -44378,8 +44312,6 @@ components: type: object description: Initial challenge being sent, define fields properties: - type: - $ref: '#/components/schemas/ChallengeChoices' flow_info: $ref: '#/components/schemas/ContextualFlowInfo' component: @@ -44397,7 +44329,6 @@ components: $ref: '#/components/schemas/StagePrompt' required: - fields - - type PromptChallengeResponseRequest: type: object description: |- @@ -45459,8 +45390,6 @@ components: type: object description: Challenge type to redirect the client properties: - type: - $ref: '#/components/schemas/ChallengeChoices' flow_info: $ref: '#/components/schemas/ContextualFlowInfo' component: @@ -45476,7 +45405,6 @@ components: type: string required: - to - - type Reputation: type: object description: Reputation Serializer @@ -46959,8 +46887,6 @@ components: type: object description: challenge type to render HTML as-is properties: - type: - $ref: '#/components/schemas/ChallengeChoices' flow_info: $ref: '#/components/schemas/ContextualFlowInfo' component: @@ -46976,7 +46902,6 @@ components: type: string required: - body - - type SignatureAlgorithmEnum: enum: - http://www.w3.org/2000/09/xmldsig#rsa-sha1 @@ -48097,8 +48022,6 @@ components: type: object description: Empty challenge properties: - type: - $ref: '#/components/schemas/ChallengeChoices' flow_info: $ref: '#/components/schemas/ContextualFlowInfo' component: @@ -48117,7 +48040,6 @@ components: required: - pending_user - pending_user_avatar - - type UserLoginChallengeResponseRequest: type: object description: User login challenge diff --git a/web/src/flow/FlowExecutor.ts b/web/src/flow/FlowExecutor.ts index 0ad9f32920..528686e30c 100644 --- a/web/src/flow/FlowExecutor.ts +++ b/web/src/flow/FlowExecutor.ts @@ -33,7 +33,6 @@ import PFBase from "@patternfly/patternfly/patternfly-base.css"; import { CapabilitiesEnum, - ChallengeChoices, ChallengeTypes, ContextualFlowInfo, FetchError, @@ -254,7 +253,6 @@ export class FlowExecutor extends Interface implements StageHost { body = error.message; } const challenge: FlowErrorChallenge = { - type: ChallengeChoices.Native, component: "ak-stage-flow-error", error: body, requestId: "", @@ -280,7 +278,11 @@ export class FlowExecutor extends Interface implements StageHost { } } - async renderChallengeNativeElement(): Promise { + async renderChallenge(): Promise { + if (!this.challenge) { + return html` + `; + } switch (this.challenge?.component) { case "ak-stage-access-denied": await import("@goauthentik/flow/stages/access_denied/AccessDeniedStage"); @@ -411,31 +413,17 @@ export class FlowExecutor extends Interface implements StageHost { .host=${this as StageHost} .challenge=${this.challenge} >`; - default: - return html`Invalid native challenge element`; - } - } - - async renderChallenge(): Promise { - if (!this.challenge) { - return html` - `; - } - switch (this.challenge.type) { - case ChallengeChoices.Redirect: + case "xak-flow-redirect": return html` `; - case ChallengeChoices.Shell: + case "xak-flow-shell": return html`${unsafeHTML((this.challenge as ShellChallenge).body)}`; - case ChallengeChoices.Native: - return await this.renderChallengeNativeElement(); default: - console.debug(`authentik/flows: unexpected data type ${this.challenge.type}`); - return html``; + return html`Invalid native challenge element`; } } diff --git a/web/src/flow/stages/access_denied/AccessDeniedStage.stories.ts b/web/src/flow/stages/access_denied/AccessDeniedStage.stories.ts index f6711f274c..876b382dd4 100644 --- a/web/src/flow/stages/access_denied/AccessDeniedStage.stories.ts +++ b/web/src/flow/stages/access_denied/AccessDeniedStage.stories.ts @@ -4,7 +4,7 @@ import { html } from "lit"; import "@patternfly/patternfly/components/Login/login.css"; -import { AccessDeniedChallenge, ChallengeChoices, UiThemeEnum } from "@goauthentik/api"; +import { AccessDeniedChallenge, UiThemeEnum } from "@goauthentik/api"; import "../../../stories/flow-interface"; import "./AccessDeniedStage"; @@ -39,7 +39,6 @@ export const Challenge: StoryObj = { args: { theme: "automatic", challenge: { - type: ChallengeChoices.Native, pendingUser: "foo", pendingUserAvatar: "https://picsum.photos/64", errorMessage: "This is an error message", diff --git a/web/src/flow/stages/authenticator_totp/AuthenticatorTOTPStage.stories.ts b/web/src/flow/stages/authenticator_totp/AuthenticatorTOTPStage.stories.ts index 24a4f4a4a8..b687a7fd06 100644 --- a/web/src/flow/stages/authenticator_totp/AuthenticatorTOTPStage.stories.ts +++ b/web/src/flow/stages/authenticator_totp/AuthenticatorTOTPStage.stories.ts @@ -4,7 +4,7 @@ import { html } from "lit"; import "@patternfly/patternfly/components/Login/login.css"; -import { AuthenticatorTOTPChallenge, ChallengeChoices, UiThemeEnum } from "@goauthentik/api"; +import { AuthenticatorTOTPChallenge, UiThemeEnum } from "@goauthentik/api"; import "../../../stories/flow-interface"; import "./AuthenticatorTOTPStage"; @@ -41,7 +41,6 @@ export const Challenge: StoryObj = { args: { theme: "automatic", challenge: { - type: ChallengeChoices.Native, pendingUser: "foo", pendingUserAvatar: "https://picsum.photos/64", configUrl: "", diff --git a/web/src/flow/stages/captcha/CaptchaStage.stories.ts b/web/src/flow/stages/captcha/CaptchaStage.stories.ts index 668eaf1b59..a6196d9766 100644 --- a/web/src/flow/stages/captcha/CaptchaStage.stories.ts +++ b/web/src/flow/stages/captcha/CaptchaStage.stories.ts @@ -4,7 +4,7 @@ import { html } from "lit"; import "@patternfly/patternfly/components/Login/login.css"; -import { CaptchaChallenge, ChallengeChoices, UiThemeEnum } from "@goauthentik/api"; +import { CaptchaChallenge, UiThemeEnum } from "@goauthentik/api"; import "../../../stories/flow-interface"; import "./CaptchaStage"; @@ -39,7 +39,6 @@ export const ChallengeGoogleReCaptcha: StoryObj = { args: { theme: "automatic", challenge: { - type: ChallengeChoices.Native, pendingUser: "foo", pendingUserAvatar: "https://picsum.photos/64", jsUrl: "https://www.google.com/recaptcha/api.js", @@ -70,7 +69,6 @@ export const ChallengeHCaptcha: StoryObj = { args: { theme: "automatic", challenge: { - type: ChallengeChoices.Native, pendingUser: "foo", pendingUserAvatar: "https://picsum.photos/64", jsUrl: "https://js.hcaptcha.com/1/api.js", @@ -101,7 +99,6 @@ export const ChallengeTurnstile: StoryObj = { args: { theme: "automatic", challenge: { - type: ChallengeChoices.Native, pendingUser: "foo", pendingUserAvatar: "https://picsum.photos/64", jsUrl: "https://challenges.cloudflare.com/turnstile/v0/api.js", diff --git a/web/src/user/user-settings/details/UserSettingsFlowExecutor.ts b/web/src/user/user-settings/details/UserSettingsFlowExecutor.ts index b1c477170d..11f9aba969 100644 --- a/web/src/user/user-settings/details/UserSettingsFlowExecutor.ts +++ b/web/src/user/user-settings/details/UserSettingsFlowExecutor.ts @@ -20,7 +20,6 @@ import PFPage from "@patternfly/patternfly/components/Page/page.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css"; import { - ChallengeChoices, ChallengeTypes, FlowChallengeResponseRequest, FlowErrorChallenge, @@ -116,7 +115,6 @@ export class UserSettingsFlowExecutor body = error.message; } const challenge: FlowErrorChallenge = { - type: ChallengeChoices.Native, component: "ak-stage-flow-error", error: body, requestId: "", @@ -146,8 +144,15 @@ export class UserSettingsFlowExecutor if (!this.challenge) { return html``; } - switch (this.challenge.type) { - case ChallengeChoices.Redirect: + switch (this.challenge.component) { + case "ak-stage-prompt": + return html``; + case "xak-flow-shell": + return html`${unsafeHTML((this.challenge as ShellChallenge).body)}`; + case "xak-flow-redirect": if ((this.challenge as RedirectChallenge).to !== "/") { return html` `; - case ChallengeChoices.Shell: - return html`${unsafeHTML((this.challenge as ShellChallenge).body)}`; - case ChallengeChoices.Native: - switch (this.challenge.component) { - case "ak-stage-prompt": - return html``; - default: - console.debug( - `authentik/user/flows: unsupported stage type ${this.challenge.component}`, - ); - return html` - - ${msg("Open settings")} - - `; - } default: - console.debug(`authentik/user/flows: unexpected data type ${this.challenge.type}`); - break; + console.debug( + `authentik/user/flows: unsupported stage type ${this.challenge.component}`, + ); + return html` + + ${msg("Open settings")} + + `; } - return html``; } renderChallengeWrapper(): TemplateResult {