stages/password: add constants for password backends

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2021-06-12 12:14:55 +02:00
parent 6661af032d
commit 10d949f7a9
14 changed files with 35 additions and 27 deletions

View File

@ -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,

View File

@ -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(

View File

@ -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"""

View File

@ -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")

View File

@ -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,
}, },
) )

View File

@ -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()

View File

@ -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()

View File

@ -0,0 +1,3 @@
"""Backend paths"""
BACKEND_DJANGO = "django.contrib.auth.backends.ModelBackend"
BACKEND_LDAP = "authentik.sources.ldap.auth.LDAPBackend"

View File

@ -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"),
), ),
] ]

View File

@ -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)

View File

@ -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,

View File

@ -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()

View File

@ -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"
]
} }
}, },
{ {

View File

@ -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"
]
} }
}, },
{ {