From daf11a8c3ae99d28a5c63eb801dc3be4b0acafeb Mon Sep 17 00:00:00 2001 From: Art Lukyanchyk <artiom.lukyanchyk@hs-hannover.de> Date: Mon, 21 Aug 2017 14:55:24 +0200 Subject: [PATCH] Implement proper redirects after log in and log out. --- ssoauth/templates/ssoauth/dev.html | 4 ++-- ssoauth/urls.py | 2 +- ssoauth/views.py | 32 +++++++++++++++++++++--------- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/ssoauth/templates/ssoauth/dev.html b/ssoauth/templates/ssoauth/dev.html index 67d678d..bbf8937 100644 --- a/ssoauth/templates/ssoauth/dev.html +++ b/ssoauth/templates/ssoauth/dev.html @@ -34,8 +34,8 @@ </div> <div class="column"> <h4 class="title">Production Actions</h4> - <a class="button button-outline button-black" href="{% url "sso-login" %}">SSO Log in</a> - <a class="button button-outline button-black" href="{% url "sso-logout" %}">Log out</a> + <a class="button button-outline button-black" href="{% url "sso-login" %}?next={% url "sso-dev" %}">SSO Log in</a> + <a class="button button-outline button-black" href="{% url "sso-logout" %}?next={% url "sso-dev" %}">Log out</a> <p><i>These actions are used in production</i></p> </div> </div> diff --git a/ssoauth/urls.py b/ssoauth/urls.py index a291deb..f63ebf5 100644 --- a/ssoauth/urls.py +++ b/ssoauth/urls.py @@ -6,6 +6,6 @@ urlpatterns = ( url(r"^logout/?$", views.LogOutView.as_view(), name="sso-logout"), url(r"^saml2/acs/?$", views.ACSAuthNView.as_view(), name="sso-saml2-acs"), url(r"^saml2/meta/?$", views.MetadataView.as_view(), name="sso-saml2-meta"), - url(r"^d(?:ev)?/?$", views.DevView.as_view(), name="sso-dev"), + url(r"^dev/?$", views.DevView.as_view(), name="sso-dev"), ) diff --git a/ssoauth/views.py b/ssoauth/views.py index 2637756..d8785f4 100644 --- a/ssoauth/views.py +++ b/ssoauth/views.py @@ -5,13 +5,14 @@ from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt from django.contrib import auth as contrib_auth from django.contrib.auth import models as contrib_auth_models +from django.contrib.auth import REDIRECT_FIELD_NAME from django import conf from django.core import exceptions from django import forms +from django.views.decorators.cache import never_cache from . import logger from . import app_settings from . import auth_utils -from onelogin.saml2.utils import OneLogin_Saml2_Utils from onelogin.saml2.auth import OneLogin_Saml2_Auth from collections import OrderedDict @@ -50,26 +51,30 @@ class SAMLMixin: ) +@method_decorator(never_cache, "dispatch") class LogInView(SAMLMixin, View): def get(self, request, *args, **kwargs): - next_url = "{host}{relative}".format( - host=OneLogin_Saml2_Utils.get_self_url(self.get_onelogin_request_data(request)), - relative=urls.reverse("sso-saml2-meta"), - ) auth = self.get_onelogin_auth(request) - login = auth.login(return_to=next_url) + login = auth.login(return_to=self.get_next_url(request)) return http.HttpResponseRedirect(login) + @staticmethod + def get_next_url(request): + next_url = request.GET.get(REDIRECT_FIELD_NAME, None) or conf.settings.LOGIN_REDIRECT_URL or "/" + logger.debug("Will ask IDP to redirect after login to: {}".format(next_url)) + return next_url + class LogOutView(View): def get(self, request, *args, **kwargs): contrib_auth.logout(request) - logger.warning("Don't know what to do after logging out in Django.") - return http.HttpResponseRedirect(urls.reverse("sso-dev")) + next_url = request.GET.get(REDIRECT_FIELD_NAME, None) or conf.settings.LOGOUT_REDIRECT_URL or "/" + return http.HttpResponseRedirect(next_url) +@method_decorator(never_cache, "dispatch") @method_decorator(csrf_exempt, "dispatch") class ACSAuthNView(SAMLMixin, View): """ @@ -84,11 +89,20 @@ class ACSAuthNView(SAMLMixin, View): self.log_in_user(request, auth) if conf.settings.DEBUG: request.session["DEBUG_SAML2_ATTRS"] = auth.get_attributes() - return http.HttpResponseRedirect(urls.reverse("sso-dev")) + return http.HttpResponseRedirect(self.get_next_url(request)) else: logger.error("Not authenticated. Errors: {0}".format(auth.get_errors())) raise exceptions.PermissionDenied() + @staticmethod + def get_next_url(request): + next_url = request.POST.get("RelayState", None) + if not next_url: + logger.warning("Did not receive RelayState (redirect target) from the IDP.") + next_url = conf.settings.LOGOUT_REDIRECT_URL or "/" + logger.debug("From ACS redirecting to {}".format(next_url)) + return next_url + def log_in_user(self, request, auth): def get_attr(attribute_name, nullable=False, multivalued=False): -- GitLab