providers/saml: fix error when using post bindings and user freshly logged in

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#1873
This commit is contained in:
Jens Langhammer 2021-12-02 12:56:29 +01:00
parent f0d7edb963
commit 4f54ce6afb
3 changed files with 17 additions and 6 deletions

View file

@ -53,6 +53,7 @@ NEXT_ARG_NAME = "next"
SESSION_KEY_PLAN = "authentik_flows_plan" SESSION_KEY_PLAN = "authentik_flows_plan"
SESSION_KEY_APPLICATION_PRE = "authentik_flows_application_pre" SESSION_KEY_APPLICATION_PRE = "authentik_flows_application_pre"
SESSION_KEY_GET = "authentik_flows_get" SESSION_KEY_GET = "authentik_flows_get"
SESSION_KEY_POST = "authentik_flows_post"
SESSION_KEY_HISTORY = "authentik_flows_history" SESSION_KEY_HISTORY = "authentik_flows_history"

View file

@ -10,7 +10,7 @@ from django.views.generic.base import View
from structlog.stdlib import get_logger from structlog.stdlib import get_logger
from authentik.core.models import Application, Provider, User from authentik.core.models import Application, Provider, User
from authentik.flows.views.executor import SESSION_KEY_APPLICATION_PRE from authentik.flows.views.executor import SESSION_KEY_APPLICATION_PRE, SESSION_KEY_POST
from authentik.lib.sentry import SentryIgnoredException from authentik.lib.sentry import SentryIgnoredException
from authentik.policies.denied import AccessDeniedResponse from authentik.policies.denied import AccessDeniedResponse
from authentik.policies.engine import PolicyEngine from authentik.policies.engine import PolicyEngine
@ -84,6 +84,10 @@ class PolicyAccessView(AccessMixin, View):
a hint on the Identification Stage what the user should login for.""" a hint on the Identification Stage what the user should login for."""
if self.application: if self.application:
self.request.session[SESSION_KEY_APPLICATION_PRE] = self.application self.request.session[SESSION_KEY_APPLICATION_PRE] = self.application
# Because this view might get hit with a POST request, we need to preserve that data
# since later views might need it (mostly SAML)
if self.request.method.lower() == "post":
self.request.session[SESSION_KEY_POST] = self.request.POST
return redirect_to_login( return redirect_to_login(
self.request.get_full_path(), self.request.get_full_path(),
self.get_login_url(), self.get_login_url(),

View file

@ -13,7 +13,7 @@ from authentik.core.models import Application
from authentik.events.models import Event, EventAction from authentik.events.models import Event, EventAction
from authentik.flows.models import in_memory_stage from authentik.flows.models import in_memory_stage
from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, PLAN_CONTEXT_SSO, FlowPlanner from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, PLAN_CONTEXT_SSO, FlowPlanner
from authentik.flows.views.executor import SESSION_KEY_PLAN from authentik.flows.views.executor import SESSION_KEY_PLAN, SESSION_KEY_POST
from authentik.lib.utils.urls import redirect_with_qs from authentik.lib.utils.urls import redirect_with_qs
from authentik.lib.views import bad_request_message from authentik.lib.views import bad_request_message
from authentik.policies.views import PolicyAccessView from authentik.policies.views import PolicyAccessView
@ -37,7 +37,7 @@ LOGGER = get_logger()
class SAMLSSOView(PolicyAccessView): class SAMLSSOView(PolicyAccessView):
""" "SAML SSO Base View, which plans a flow and injects our final stage. """SAML SSO Base View, which plans a flow and injects our final stage.
Calls get/post handler.""" Calls get/post handler."""
def resolve_provider_application(self): def resolve_provider_application(self):
@ -120,14 +120,20 @@ class SAMLSSOBindingPOSTView(SAMLSSOView):
def check_saml_request(self) -> Optional[HttpRequest]: def check_saml_request(self) -> Optional[HttpRequest]:
"""Handle POST bindings""" """Handle POST bindings"""
if REQUEST_KEY_SAML_REQUEST not in self.request.POST: payload = self.request.POST
# Restore the post body from the session
# This happens when using POST bindings but the user isn't logged in
# (user gets redirected and POST body is 'lost')
if SESSION_KEY_POST in self.request.session:
payload = self.request.session[SESSION_KEY_POST]
if REQUEST_KEY_SAML_REQUEST not in payload:
LOGGER.info("check_saml_request: SAML payload missing") LOGGER.info("check_saml_request: SAML payload missing")
return bad_request_message(self.request, "The SAML request payload is missing.") return bad_request_message(self.request, "The SAML request payload is missing.")
try: try:
auth_n_request = AuthNRequestParser(self.provider).parse( auth_n_request = AuthNRequestParser(self.provider).parse(
self.request.POST[REQUEST_KEY_SAML_REQUEST], payload[REQUEST_KEY_SAML_REQUEST],
self.request.POST.get(REQUEST_KEY_RELAY_STATE), payload.get(REQUEST_KEY_RELAY_STATE),
) )
self.request.session[SESSION_KEY_AUTH_N_REQUEST] = auth_n_request self.request.session[SESSION_KEY_AUTH_N_REQUEST] = auth_n_request
except CannotHandleAssertion as exc: except CannotHandleAssertion as exc: