From 5b22f9b6c35960b99b3840e99bf85c6c8fc9041b Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Tue, 18 Feb 2020 10:57:30 +0100 Subject: [PATCH] providers/saml: transition to dataclass from dict, cleanup unused templates, add missing autosubmit_form --- passbook/providers/saml/exceptions.py | 4 - passbook/providers/saml/models.py | 2 +- passbook/providers/saml/processors/base.py | 24 +-- passbook/providers/saml/processors/types.py | 11 ++ .../templates/saml/idp/autosubmit_form.html | 39 ++++ .../saml/templates/saml/idp/invalid_user.html | 5 - .../saml/templates/saml/idp/logged_out.html | 10 +- .../saml/templates/saml/idp/login.html | 12 +- .../saml/templates/saml/idp/settings.html | 47 ----- passbook/providers/saml/urls.py | 9 +- passbook/providers/saml/views.py | 177 +++++++++++------- passbook/root/settings.py | 2 +- 12 files changed, 190 insertions(+), 152 deletions(-) create mode 100644 passbook/providers/saml/processors/types.py create mode 100644 passbook/providers/saml/templates/saml/idp/autosubmit_form.html delete mode 100644 passbook/providers/saml/templates/saml/idp/invalid_user.html delete mode 100644 passbook/providers/saml/templates/saml/idp/settings.html diff --git a/passbook/providers/saml/exceptions.py b/passbook/providers/saml/exceptions.py index 98fea6dec..a78218ca6 100644 --- a/passbook/providers/saml/exceptions.py +++ b/passbook/providers/saml/exceptions.py @@ -3,7 +3,3 @@ class CannotHandleAssertion(Exception): """This processor does not handle this assertion.""" - - -class UserNotAuthorized(Exception): - """User not authorized for SAML 2.0 authentication.""" diff --git a/passbook/providers/saml/models.py b/passbook/providers/saml/models.py index d69c2d189..4a1668b77 100644 --- a/passbook/providers/saml/models.py +++ b/passbook/providers/saml/models.py @@ -82,7 +82,7 @@ class SAMLProvider(Provider): self._meta.get_field("processor_path").choices = get_provider_choices() @property - def processor(self): + def processor(self) -> Processor: """Return selected processor as instance""" if not self._processor: try: diff --git a/passbook/providers/saml/processors/base.py b/passbook/providers/saml/processors/base.py index 13d51b4ba..c407d44d0 100644 --- a/passbook/providers/saml/processors/base.py +++ b/passbook/providers/saml/processors/base.py @@ -7,6 +7,7 @@ from structlog import get_logger from passbook.core.exceptions import PropertyMappingExpressionException from passbook.providers.saml.exceptions import CannotHandleAssertion +from passbook.providers.saml.processors.types import SAMLResponseParams from passbook.providers.saml.utils import get_random_id from passbook.providers.saml.utils.encoding import decode_base64_and_inflate, nice64 from passbook.providers.saml.utils.time import get_time_string, timedelta_from_string @@ -133,14 +134,13 @@ class Processor: self._response_params, saml_provider=self._remote, assertion_id=assertion_id ) - def _get_django_response_params(self) -> Dict[str, str]: + def _get_saml_response_params(self) -> SAMLResponseParams: """Returns a dictionary of parameters for the response template.""" - return { - "acs_url": self._request_params["ACS_URL"], - "saml_response": self._saml_response, - "relay_state": self._relay_state, - "autosubmit": self._remote.application.skip_authorization, - } + return SAMLResponseParams( + acs_url=self._request_params["ACS_URL"], + saml_response=self._saml_response, + relay_state=self._relay_state, + ) def _decode_and_parse_request(self): """Parses various parameters from _request_xml into _request_params.""" @@ -183,7 +183,7 @@ class Processor: # Read the request. try: self._extract_saml_request() - except Exception as exc: + except KeyError as exc: raise CannotHandleAssertion( f"can't find SAML request in user session: {exc}" ) from exc @@ -196,7 +196,7 @@ class Processor: self._validate_request() return True - def generate_response(self) -> Dict[str, str]: + def generate_response(self) -> SAMLResponseParams: """Processes request and returns template variables suitable for a response.""" # Build the assertion and response. # Only call can_handle if SP initiated Request, otherwise we have no Request @@ -210,9 +210,9 @@ class Processor: self._encode_response() # Return proper template params. - return self._get_django_response_params() + return self._get_saml_response_params() - def init_deep_link(self, request: HttpRequest, url: str): + def init_deep_link(self, request: HttpRequest): """Initialize this Processor to make an IdP-initiated call to the SP's deep-linked URL.""" self._http_request = request @@ -227,4 +227,4 @@ class Processor: "DESTINATION": "", "PROVIDER_NAME": "", } - self._relay_state = url + self._relay_state = "" diff --git a/passbook/providers/saml/processors/types.py b/passbook/providers/saml/processors/types.py new file mode 100644 index 000000000..a283ba06e --- /dev/null +++ b/passbook/providers/saml/processors/types.py @@ -0,0 +1,11 @@ +"""passbook saml provider types""" +from dataclasses import dataclass + + +@dataclass +class SAMLResponseParams: + """Class to keep track of SAML Response Parameters""" + + acs_url: str + saml_response: str + relay_state: str diff --git a/passbook/providers/saml/templates/saml/idp/autosubmit_form.html b/passbook/providers/saml/templates/saml/idp/autosubmit_form.html new file mode 100644 index 000000000..99166d5e9 --- /dev/null +++ b/passbook/providers/saml/templates/saml/idp/autosubmit_form.html @@ -0,0 +1,39 @@ +{% extends "login/base.html" %} + +{% load utils %} +{% load i18n %} + +{% block title %} +{% title 'Redirecting...' %} +{% endblock %} + +{% block card %} +
+

{% trans 'Redirecting...' %}

+
+
+ {% csrf_token %} + {% for key, value in attrs.items %} + + {% endfor %} + +
+{% endblock %} + +{% block scripts %} +{{ block.super }} + +{% endblock %} diff --git a/passbook/providers/saml/templates/saml/idp/invalid_user.html b/passbook/providers/saml/templates/saml/idp/invalid_user.html deleted file mode 100644 index 16ba1f4e6..000000000 --- a/passbook/providers/saml/templates/saml/idp/invalid_user.html +++ /dev/null @@ -1,5 +0,0 @@ -{% extends "saml/idp/base.html" %} -{% load i18n %} -{% block content %} -{% trans "You have logged in, but your user account is not enabled for SAML 2.0." %} -{% endblock %} diff --git a/passbook/providers/saml/templates/saml/idp/logged_out.html b/passbook/providers/saml/templates/saml/idp/logged_out.html index 2d973d442..4b2a98b74 100644 --- a/passbook/providers/saml/templates/saml/idp/logged_out.html +++ b/passbook/providers/saml/templates/saml/idp/logged_out.html @@ -1,5 +1,9 @@ -{% extends "saml/idp/base.html" %} +{% extends "login/base.html" %} + {% load i18n %} -{% block content %} -{% trans "You have successfully logged out of the Identity Provider." %} + +{% block card %} +

+ {% trans "You have successfully logged out of the Identity Provider." %} +

{% endblock %} diff --git a/passbook/providers/saml/templates/saml/idp/login.html b/passbook/providers/saml/templates/saml/idp/login.html index 13fc082b3..6c0f5e80e 100644 --- a/passbook/providers/saml/templates/saml/idp/login.html +++ b/passbook/providers/saml/templates/saml/idp/login.html @@ -11,15 +11,15 @@

{% trans 'Authorize Application' %}

-
+ {% csrf_token %} - - - + + +