stages/password: add constants for password backends
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
6661af032d
commit
10d949f7a9
|
@ -33,6 +33,7 @@ from authentik.flows.planner import (
|
||||||
from authentik.flows.views import NEXT_ARG_NAME, SESSION_KEY_GET, SESSION_KEY_PLAN
|
from authentik.flows.views import NEXT_ARG_NAME, SESSION_KEY_GET, SESSION_KEY_PLAN
|
||||||
from authentik.lib.utils.urls import redirect_with_qs
|
from authentik.lib.utils.urls import redirect_with_qs
|
||||||
from authentik.policies.utils import delete_none_keys
|
from authentik.policies.utils import delete_none_keys
|
||||||
|
from authentik.stages.password import BACKEND_DJANGO
|
||||||
from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
||||||
from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT
|
from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT
|
||||||
|
|
||||||
|
@ -198,7 +199,7 @@ class SourceFlowManager:
|
||||||
kwargs.update(
|
kwargs.update(
|
||||||
{
|
{
|
||||||
# Since we authenticate the user by their token, they have no backend set
|
# Since we authenticate the user by their token, they have no backend set
|
||||||
PLAN_CONTEXT_AUTHENTICATION_BACKEND: "django.contrib.auth.backends.ModelBackend",
|
PLAN_CONTEXT_AUTHENTICATION_BACKEND: BACKEND_DJANGO,
|
||||||
PLAN_CONTEXT_SSO: True,
|
PLAN_CONTEXT_SSO: True,
|
||||||
PLAN_CONTEXT_SOURCE: self.source,
|
PLAN_CONTEXT_SOURCE: self.source,
|
||||||
PLAN_CONTEXT_REDIRECT: final_redirect,
|
PLAN_CONTEXT_REDIRECT: final_redirect,
|
||||||
|
|
|
@ -6,6 +6,7 @@ from django.db.backends.base.schema import BaseDatabaseSchemaEditor
|
||||||
|
|
||||||
from authentik.flows.models import FlowDesignation
|
from authentik.flows.models import FlowDesignation
|
||||||
from authentik.stages.identification.models import UserFields
|
from authentik.stages.identification.models import UserFields
|
||||||
|
from authentik.stages.password import BACKEND_DJANGO, BACKEND_LDAP
|
||||||
|
|
||||||
|
|
||||||
def create_default_authentication_flow(
|
def create_default_authentication_flow(
|
||||||
|
@ -31,7 +32,7 @@ def create_default_authentication_flow(
|
||||||
|
|
||||||
password_stage, _ = PasswordStage.objects.using(db_alias).update_or_create(
|
password_stage, _ = PasswordStage.objects.using(db_alias).update_or_create(
|
||||||
name="default-authentication-password",
|
name="default-authentication-password",
|
||||||
defaults={"backends": ["django.contrib.auth.backends.ModelBackend"]},
|
defaults={"backends": [BACKEND_DJANGO, BACKEND_LDAP]},
|
||||||
)
|
)
|
||||||
|
|
||||||
login_stage, _ = UserLoginStage.objects.using(db_alias).update_or_create(
|
login_stage, _ = UserLoginStage.objects.using(db_alias).update_or_create(
|
||||||
|
|
|
@ -15,9 +15,6 @@ PREFILL_POLICY_EXPRESSION = """# This policy sets the user for the currently run
|
||||||
# by injecting "pending_user"
|
# by injecting "pending_user"
|
||||||
akadmin = ak_user_by(username="akadmin")
|
akadmin = ak_user_by(username="akadmin")
|
||||||
context["pending_user"] = akadmin
|
context["pending_user"] = akadmin
|
||||||
# We're also setting the backend for the user, so we can
|
|
||||||
# directly login without having to identify again
|
|
||||||
context["user_backend"] = "django.contrib.auth.backends.ModelBackend"
|
|
||||||
return True"""
|
return True"""
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ from django.utils.translation import gettext as _
|
||||||
from django.views import View
|
from django.views import View
|
||||||
|
|
||||||
from authentik.core.models import Token, TokenIntents
|
from authentik.core.models import Token, TokenIntents
|
||||||
|
from authentik.stages.password import BACKEND_DJANGO
|
||||||
|
|
||||||
|
|
||||||
class UseTokenView(View):
|
class UseTokenView(View):
|
||||||
|
@ -18,7 +19,7 @@ class UseTokenView(View):
|
||||||
if not tokens.exists():
|
if not tokens.exists():
|
||||||
raise Http404
|
raise Http404
|
||||||
token = tokens.first()
|
token = tokens.first()
|
||||||
login(request, token.user, backend="django.contrib.auth.backends.ModelBackend")
|
login(request, token.user, backend=BACKEND_DJANGO)
|
||||||
token.delete()
|
token.delete()
|
||||||
messages.warning(request, _("Used recovery-link to authenticate."))
|
messages.warning(request, _("Used recovery-link to authenticate."))
|
||||||
return redirect("authentik_core:if-admin")
|
return redirect("authentik_core:if-admin")
|
||||||
|
|
|
@ -39,7 +39,7 @@ from authentik.sources.saml.processors.constants import (
|
||||||
from authentik.sources.saml.processors.request import SESSION_REQUEST_ID
|
from authentik.sources.saml.processors.request import SESSION_REQUEST_ID
|
||||||
from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
||||||
from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT
|
from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT
|
||||||
from authentik.stages.user_login.stage import DEFAULT_BACKEND
|
from authentik.stages.user_login.stage import BACKEND_DJANGO
|
||||||
|
|
||||||
LOGGER = get_logger()
|
LOGGER = get_logger()
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
@ -141,7 +141,7 @@ class ResponseProcessor:
|
||||||
self._source.authentication_flow,
|
self._source.authentication_flow,
|
||||||
**{
|
**{
|
||||||
PLAN_CONTEXT_PENDING_USER: user,
|
PLAN_CONTEXT_PENDING_USER: user,
|
||||||
PLAN_CONTEXT_AUTHENTICATION_BACKEND: DEFAULT_BACKEND,
|
PLAN_CONTEXT_AUTHENTICATION_BACKEND: BACKEND_DJANGO,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -204,7 +204,7 @@ class ResponseProcessor:
|
||||||
self._source.authentication_flow,
|
self._source.authentication_flow,
|
||||||
**{
|
**{
|
||||||
PLAN_CONTEXT_PENDING_USER: matching_users.first(),
|
PLAN_CONTEXT_PENDING_USER: matching_users.first(),
|
||||||
PLAN_CONTEXT_AUTHENTICATION_BACKEND: DEFAULT_BACKEND,
|
PLAN_CONTEXT_AUTHENTICATION_BACKEND: BACKEND_DJANGO,
|
||||||
PLAN_CONTEXT_REDIRECT: final_redirect,
|
PLAN_CONTEXT_REDIRECT: final_redirect,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,6 +9,7 @@ from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding
|
||||||
from authentik.providers.oauth2.generators import generate_client_secret
|
from authentik.providers.oauth2.generators import generate_client_secret
|
||||||
from authentik.sources.oauth.models import OAuthSource
|
from authentik.sources.oauth.models import OAuthSource
|
||||||
from authentik.stages.identification.models import IdentificationStage, UserFields
|
from authentik.stages.identification.models import IdentificationStage, UserFields
|
||||||
|
from authentik.stages.password import BACKEND_DJANGO
|
||||||
from authentik.stages.password.models import PasswordStage
|
from authentik.stages.password.models import PasswordStage
|
||||||
|
|
||||||
|
|
||||||
|
@ -70,7 +71,7 @@ class TestIdentificationStage(TestCase):
|
||||||
def test_valid_with_password(self):
|
def test_valid_with_password(self):
|
||||||
"""Test with valid email and password in single step"""
|
"""Test with valid email and password in single step"""
|
||||||
pw_stage = PasswordStage.objects.create(
|
pw_stage = PasswordStage.objects.create(
|
||||||
name="password", backends=["django.contrib.auth.backends.ModelBackend"]
|
name="password", backends=[BACKEND_DJANGO]
|
||||||
)
|
)
|
||||||
self.stage.password_stage = pw_stage
|
self.stage.password_stage = pw_stage
|
||||||
self.stage.save()
|
self.stage.save()
|
||||||
|
@ -92,7 +93,7 @@ class TestIdentificationStage(TestCase):
|
||||||
def test_invalid_with_password(self):
|
def test_invalid_with_password(self):
|
||||||
"""Test with valid email and invalid password in single step"""
|
"""Test with valid email and invalid password in single step"""
|
||||||
pw_stage = PasswordStage.objects.create(
|
pw_stage = PasswordStage.objects.create(
|
||||||
name="password", backends=["django.contrib.auth.backends.ModelBackend"]
|
name="password", backends=[BACKEND_DJANGO]
|
||||||
)
|
)
|
||||||
self.stage.password_stage = pw_stage
|
self.stage.password_stage = pw_stage
|
||||||
self.stage.save()
|
self.stage.save()
|
||||||
|
|
|
@ -17,6 +17,7 @@ from authentik.flows.tests.test_views import TO_STAGE_RESPONSE_MOCK
|
||||||
from authentik.flows.views import SESSION_KEY_PLAN
|
from authentik.flows.views import SESSION_KEY_PLAN
|
||||||
from authentik.stages.invitation.models import Invitation, InvitationStage
|
from authentik.stages.invitation.models import Invitation, InvitationStage
|
||||||
from authentik.stages.invitation.stage import INVITATION_TOKEN_KEY, PLAN_CONTEXT_PROMPT
|
from authentik.stages.invitation.stage import INVITATION_TOKEN_KEY, PLAN_CONTEXT_PROMPT
|
||||||
|
from authentik.stages.password import BACKEND_DJANGO
|
||||||
from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,9 +47,7 @@ class TestUserLoginStage(TestCase):
|
||||||
flow_pk=self.flow.pk.hex, stages=[self.stage], markers=[StageMarker()]
|
flow_pk=self.flow.pk.hex, stages=[self.stage], markers=[StageMarker()]
|
||||||
)
|
)
|
||||||
plan.context[PLAN_CONTEXT_PENDING_USER] = self.user
|
plan.context[PLAN_CONTEXT_PENDING_USER] = self.user
|
||||||
plan.context[
|
plan.context[PLAN_CONTEXT_AUTHENTICATION_BACKEND] = BACKEND_DJANGO
|
||||||
PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
|
||||||
] = "django.contrib.auth.backends.ModelBackend"
|
|
||||||
session = self.client.session
|
session = self.client.session
|
||||||
session[SESSION_KEY_PLAN] = plan
|
session[SESSION_KEY_PLAN] = plan
|
||||||
session.save()
|
session.save()
|
||||||
|
@ -79,9 +78,7 @@ class TestUserLoginStage(TestCase):
|
||||||
flow_pk=self.flow.pk.hex, stages=[self.stage], markers=[StageMarker()]
|
flow_pk=self.flow.pk.hex, stages=[self.stage], markers=[StageMarker()]
|
||||||
)
|
)
|
||||||
plan.context[PLAN_CONTEXT_PENDING_USER] = self.user
|
plan.context[PLAN_CONTEXT_PENDING_USER] = self.user
|
||||||
plan.context[
|
plan.context[PLAN_CONTEXT_AUTHENTICATION_BACKEND] = BACKEND_DJANGO
|
||||||
PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
|
||||||
] = "django.contrib.auth.backends.ModelBackend"
|
|
||||||
session = self.client.session
|
session = self.client.session
|
||||||
session[SESSION_KEY_PLAN] = plan
|
session[SESSION_KEY_PLAN] = plan
|
||||||
session.save()
|
session.save()
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
"""Backend paths"""
|
||||||
|
BACKEND_DJANGO = "django.contrib.auth.backends.ModelBackend"
|
||||||
|
BACKEND_LDAP = "authentik.sources.ldap.auth.LDAPBackend"
|
|
@ -9,17 +9,18 @@ from rest_framework.serializers import BaseSerializer
|
||||||
|
|
||||||
from authentik.core.types import UserSettingSerializer
|
from authentik.core.types import UserSettingSerializer
|
||||||
from authentik.flows.models import ConfigurableStage, Stage
|
from authentik.flows.models import ConfigurableStage, Stage
|
||||||
|
from authentik.stages.password import BACKEND_DJANGO, BACKEND_LDAP
|
||||||
|
|
||||||
|
|
||||||
def get_authentication_backends():
|
def get_authentication_backends():
|
||||||
"""Return all available authentication backends as tuple set"""
|
"""Return all available authentication backends as tuple set"""
|
||||||
return [
|
return [
|
||||||
(
|
(
|
||||||
"django.contrib.auth.backends.ModelBackend",
|
BACKEND_DJANGO,
|
||||||
_("authentik-internal Userdatabase"),
|
_("authentik-internal Userdatabase"),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"authentik.sources.ldap.auth.LDAPBackend",
|
BACKEND_LDAP,
|
||||||
_("authentik LDAP"),
|
_("authentik LDAP"),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -14,6 +14,7 @@ from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan
|
||||||
from authentik.flows.tests.test_views import TO_STAGE_RESPONSE_MOCK
|
from authentik.flows.tests.test_views import TO_STAGE_RESPONSE_MOCK
|
||||||
from authentik.flows.views import SESSION_KEY_PLAN
|
from authentik.flows.views import SESSION_KEY_PLAN
|
||||||
from authentik.providers.oauth2.generators import generate_client_secret
|
from authentik.providers.oauth2.generators import generate_client_secret
|
||||||
|
from authentik.stages.password import BACKEND_DJANGO
|
||||||
from authentik.stages.password.models import PasswordStage
|
from authentik.stages.password.models import PasswordStage
|
||||||
|
|
||||||
MOCK_BACKEND_AUTHENTICATE = MagicMock(side_effect=PermissionDenied("test"))
|
MOCK_BACKEND_AUTHENTICATE = MagicMock(side_effect=PermissionDenied("test"))
|
||||||
|
@ -36,7 +37,7 @@ class TestPasswordStage(TestCase):
|
||||||
designation=FlowDesignation.AUTHENTICATION,
|
designation=FlowDesignation.AUTHENTICATION,
|
||||||
)
|
)
|
||||||
self.stage = PasswordStage.objects.create(
|
self.stage = PasswordStage.objects.create(
|
||||||
name="password", backends=["django.contrib.auth.backends.ModelBackend"]
|
name="password", backends=[BACKEND_DJANGO]
|
||||||
)
|
)
|
||||||
FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2)
|
FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2)
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,10 @@ from structlog.stdlib import get_logger
|
||||||
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
|
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
|
||||||
from authentik.flows.stage import StageView
|
from authentik.flows.stage import StageView
|
||||||
from authentik.lib.utils.time import timedelta_from_string
|
from authentik.lib.utils.time import timedelta_from_string
|
||||||
|
from authentik.stages.password import BACKEND_DJANGO
|
||||||
from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
||||||
|
|
||||||
LOGGER = get_logger()
|
LOGGER = get_logger()
|
||||||
DEFAULT_BACKEND = "django.contrib.auth.backends.ModelBackend"
|
|
||||||
USER_LOGIN_AUTHENTICATED = "user_login_authenticated"
|
USER_LOGIN_AUTHENTICATED = "user_login_authenticated"
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ class UserLoginStageView(StageView):
|
||||||
LOGGER.debug(message)
|
LOGGER.debug(message)
|
||||||
return self.executor.stage_invalid()
|
return self.executor.stage_invalid()
|
||||||
backend = self.executor.plan.context.get(
|
backend = self.executor.plan.context.get(
|
||||||
PLAN_CONTEXT_AUTHENTICATION_BACKEND, DEFAULT_BACKEND
|
PLAN_CONTEXT_AUTHENTICATION_BACKEND, BACKEND_DJANGO
|
||||||
)
|
)
|
||||||
login(
|
login(
|
||||||
self.request,
|
self.request,
|
||||||
|
|
|
@ -9,6 +9,7 @@ from authentik.flows.markers import StageMarker
|
||||||
from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding
|
from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding
|
||||||
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan
|
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan
|
||||||
from authentik.flows.views import SESSION_KEY_PLAN
|
from authentik.flows.views import SESSION_KEY_PLAN
|
||||||
|
from authentik.stages.password import BACKEND_DJANGO
|
||||||
from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
from authentik.stages.password.stage import PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
||||||
from authentik.stages.user_logout.models import UserLogoutStage
|
from authentik.stages.user_logout.models import UserLogoutStage
|
||||||
|
|
||||||
|
@ -35,9 +36,7 @@ class TestUserLogoutStage(TestCase):
|
||||||
flow_pk=self.flow.pk.hex, stages=[self.stage], markers=[StageMarker()]
|
flow_pk=self.flow.pk.hex, stages=[self.stage], markers=[StageMarker()]
|
||||||
)
|
)
|
||||||
plan.context[PLAN_CONTEXT_PENDING_USER] = self.user
|
plan.context[PLAN_CONTEXT_PENDING_USER] = self.user
|
||||||
plan.context[
|
plan.context[PLAN_CONTEXT_AUTHENTICATION_BACKEND] = BACKEND_DJANGO
|
||||||
PLAN_CONTEXT_AUTHENTICATION_BACKEND
|
|
||||||
] = "django.contrib.auth.backends.ModelBackend"
|
|
||||||
session = self.client.session
|
session = self.client.session
|
||||||
session[SESSION_KEY_PLAN] = plan
|
session[SESSION_KEY_PLAN] = plan
|
||||||
session.save()
|
session.save()
|
||||||
|
|
|
@ -51,7 +51,10 @@
|
||||||
},
|
},
|
||||||
"model": "authentik_stages_password.passwordstage",
|
"model": "authentik_stages_password.passwordstage",
|
||||||
"attrs": {
|
"attrs": {
|
||||||
"backends": ["django.contrib.auth.backends.ModelBackend"]
|
"backends": [
|
||||||
|
"django.contrib.auth.backends.ModelBackend",
|
||||||
|
"authentik.sources.ldap.auth.LDAPBackend"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -54,7 +54,10 @@
|
||||||
},
|
},
|
||||||
"model": "authentik_stages_password.passwordstage",
|
"model": "authentik_stages_password.passwordstage",
|
||||||
"attrs": {
|
"attrs": {
|
||||||
"backends": ["django.contrib.auth.backends.ModelBackend"]
|
"backends": [
|
||||||
|
"django.contrib.auth.backends.ModelBackend",
|
||||||
|
"authentik.sources.ldap.auth.LDAPBackend"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
Reference in New Issue