stages/identification: dynamically find login challenges (#11571)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
@ -15,12 +15,13 @@ from authentik.sources.oauth.models import OAuthSource
|
|||||||
from authentik.sources.oauth.types.registry import SourceType, registry
|
from authentik.sources.oauth.types.registry import SourceType, registry
|
||||||
from authentik.sources.oauth.views.callback import OAuthCallback
|
from authentik.sources.oauth.views.callback import OAuthCallback
|
||||||
from authentik.sources.oauth.views.redirect import OAuthRedirect
|
from authentik.sources.oauth.views.redirect import OAuthRedirect
|
||||||
|
from authentik.stages.identification.stage import LoginChallengeMixin
|
||||||
|
|
||||||
LOGGER = get_logger()
|
LOGGER = get_logger()
|
||||||
APPLE_CLIENT_ID_PARTS = 3
|
APPLE_CLIENT_ID_PARTS = 3
|
||||||
|
|
||||||
|
|
||||||
class AppleLoginChallenge(Challenge):
|
class AppleLoginChallenge(LoginChallengeMixin, Challenge):
|
||||||
"""Special challenge for apple-native authentication flow, which happens on the client."""
|
"""Special challenge for apple-native authentication flow, which happens on the client."""
|
||||||
|
|
||||||
client_id = CharField()
|
client_id = CharField()
|
||||||
|
|||||||
@ -19,9 +19,10 @@ from authentik.core.models import (
|
|||||||
from authentik.core.types import UILoginButton, UserSettingSerializer
|
from authentik.core.types import UILoginButton, UserSettingSerializer
|
||||||
from authentik.flows.challenge import Challenge, ChallengeResponse
|
from authentik.flows.challenge import Challenge, ChallengeResponse
|
||||||
from authentik.lib.generators import generate_id
|
from authentik.lib.generators import generate_id
|
||||||
|
from authentik.stages.identification.stage import LoginChallengeMixin
|
||||||
|
|
||||||
|
|
||||||
class PlexAuthenticationChallenge(Challenge):
|
class PlexAuthenticationChallenge(LoginChallengeMixin, Challenge):
|
||||||
"""Challenge shown to the user in identification stage"""
|
"""Challenge shown to the user in identification stage"""
|
||||||
|
|
||||||
client_id = CharField()
|
client_id = CharField()
|
||||||
|
|||||||
@ -26,23 +26,31 @@ from authentik.flows.models import FlowDesignation
|
|||||||
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
|
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
|
||||||
from authentik.flows.stage import PLAN_CONTEXT_PENDING_USER_IDENTIFIER, ChallengeStageView
|
from authentik.flows.stage import PLAN_CONTEXT_PENDING_USER_IDENTIFIER, ChallengeStageView
|
||||||
from authentik.flows.views.executor import SESSION_KEY_APPLICATION_PRE, SESSION_KEY_GET
|
from authentik.flows.views.executor import SESSION_KEY_APPLICATION_PRE, SESSION_KEY_GET
|
||||||
|
from authentik.lib.utils.reflection import all_subclasses
|
||||||
from authentik.lib.utils.urls import reverse_with_qs
|
from authentik.lib.utils.urls import reverse_with_qs
|
||||||
from authentik.root.middleware import ClientIPMiddleware
|
from authentik.root.middleware import ClientIPMiddleware
|
||||||
from authentik.sources.oauth.types.apple import AppleLoginChallenge
|
|
||||||
from authentik.sources.plex.models import PlexAuthenticationChallenge
|
|
||||||
from authentik.stages.identification.models import IdentificationStage
|
from authentik.stages.identification.models import IdentificationStage
|
||||||
from authentik.stages.identification.signals import identification_failed
|
from authentik.stages.identification.signals import identification_failed
|
||||||
from authentik.stages.password.stage import authenticate
|
from authentik.stages.password.stage import authenticate
|
||||||
|
|
||||||
|
|
||||||
|
class LoginChallengeMixin:
|
||||||
|
"""Base login challenge for Identification stage"""
|
||||||
|
|
||||||
|
|
||||||
|
def get_login_serializers():
|
||||||
|
mapping = {
|
||||||
|
RedirectChallenge().fields["component"].default: RedirectChallenge,
|
||||||
|
}
|
||||||
|
for cls in all_subclasses(LoginChallengeMixin):
|
||||||
|
mapping[cls().fields["component"].default] = cls
|
||||||
|
return mapping
|
||||||
|
|
||||||
|
|
||||||
@extend_schema_field(
|
@extend_schema_field(
|
||||||
PolymorphicProxySerializer(
|
PolymorphicProxySerializer(
|
||||||
component_name="LoginChallengeTypes",
|
component_name="LoginChallengeTypes",
|
||||||
serializers={
|
serializers=get_login_serializers,
|
||||||
RedirectChallenge().fields["component"].default: RedirectChallenge,
|
|
||||||
PlexAuthenticationChallenge().fields["component"].default: PlexAuthenticationChallenge,
|
|
||||||
AppleLoginChallenge().fields["component"].default: AppleLoginChallenge,
|
|
||||||
},
|
|
||||||
resource_type_field_name="component",
|
resource_type_field_name="component",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@ -41620,14 +41620,14 @@ components:
|
|||||||
LoginChallengeTypes:
|
LoginChallengeTypes:
|
||||||
oneOf:
|
oneOf:
|
||||||
- $ref: '#/components/schemas/RedirectChallenge'
|
- $ref: '#/components/schemas/RedirectChallenge'
|
||||||
- $ref: '#/components/schemas/PlexAuthenticationChallenge'
|
|
||||||
- $ref: '#/components/schemas/AppleLoginChallenge'
|
- $ref: '#/components/schemas/AppleLoginChallenge'
|
||||||
|
- $ref: '#/components/schemas/PlexAuthenticationChallenge'
|
||||||
discriminator:
|
discriminator:
|
||||||
propertyName: component
|
propertyName: component
|
||||||
mapping:
|
mapping:
|
||||||
xak-flow-redirect: '#/components/schemas/RedirectChallenge'
|
xak-flow-redirect: '#/components/schemas/RedirectChallenge'
|
||||||
ak-source-plex: '#/components/schemas/PlexAuthenticationChallenge'
|
|
||||||
ak-source-oauth-apple: '#/components/schemas/AppleLoginChallenge'
|
ak-source-oauth-apple: '#/components/schemas/AppleLoginChallenge'
|
||||||
|
ak-source-plex: '#/components/schemas/PlexAuthenticationChallenge'
|
||||||
LoginMetrics:
|
LoginMetrics:
|
||||||
type: object
|
type: object
|
||||||
description: Login Metrics per 1h
|
description: Login Metrics per 1h
|
||||||
|
|||||||
Reference in New Issue
Block a user