providers/saml: some more cleanup, fix get_time_string when called without argument

This commit is contained in:
Jens Langhammer 2020-02-14 15:34:24 +01:00
parent e36d7928e4
commit 571373866e
3 changed files with 15 additions and 18 deletions

View File

@ -194,10 +194,6 @@ class Processor:
self._logger.info(msg) self._logger.info(msg)
raise CannotHandleAssertion(msg) raise CannotHandleAssertion(msg)
def _validate_user(self):
"""Validates the User. Sub-classes should override this and
throw an CannotHandleAssertion Exception if the validation does not succeed."""
def can_handle(self, request: HttpRequest) -> bool: def can_handle(self, request: HttpRequest) -> bool:
"""Returns true if this processor can handle this request.""" """Returns true if this processor can handle this request."""
self._http_request = request self._http_request = request
@ -224,7 +220,6 @@ class Processor:
if not self.is_idp_initiated: if not self.is_idp_initiated:
self.can_handle(self._http_request) self.can_handle(self._http_request)
self._validate_user()
self._build_assertion() self._build_assertion()
self._format_assertion() self._format_assertion()
self._build_response() self._build_response()

View File

@ -40,6 +40,8 @@ def timedelta_from_string(expr: str) -> datetime.timedelta:
def get_time_string(delta: datetime.timedelta = None) -> str: def get_time_string(delta: datetime.timedelta = None) -> str:
"""Get Data formatted in SAML format""" """Get Data formatted in SAML format"""
if delta is None:
delta = datetime.timedelta()
now = datetime.datetime.now() now = datetime.datetime.now()
final = now + delta final = now + delta
return final.strftime("%Y-%m-%dT%H:%M:%SZ") return final.strftime("%Y-%m-%dT%H:%M:%SZ")

View File

@ -1,9 +1,11 @@
"""passbook SAML IDP Views""" """passbook SAML IDP Views"""
from typing import Optional
from django.contrib.auth import logout from django.contrib.auth import logout
from django.contrib.auth.mixins import AccessMixin from django.contrib.auth.mixins import AccessMixin
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.validators import URLValidator from django.core.validators import URLValidator
from django.http import HttpResponse, HttpResponseBadRequest from django.http import HttpResponse, HttpResponseBadRequest, HttpRequest
from django.shortcuts import get_object_or_404, redirect, render, reverse from django.shortcuts import get_object_or_404, redirect, render, reverse
from django.utils.datastructures import MultiValueDictKeyError from django.utils.datastructures import MultiValueDictKeyError
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
@ -25,7 +27,7 @@ LOGGER = get_logger()
URL_VALIDATOR = URLValidator(schemes=("http", "https")) URL_VALIDATOR = URLValidator(schemes=("http", "https"))
def _generate_response(request, provider: SAMLProvider): def _generate_response(request: HttpRequest, provider: SAMLProvider):
"""Generate a SAML response using processor_instance and return it in the proper Django """Generate a SAML response using processor_instance and return it in the proper Django
response.""" response."""
try: try:
@ -42,7 +44,7 @@ def _generate_response(request, provider: SAMLProvider):
class AccessRequiredView(AccessMixin, View): class AccessRequiredView(AccessMixin, View):
"""Mixin class for Views using a provider instance""" """Mixin class for Views using a provider instance"""
_provider: SAMLProvider _provider: Optional[SAMLProvider] = None
@property @property
def provider(self) -> SAMLProvider: def provider(self) -> SAMLProvider:
@ -54,7 +56,7 @@ class AccessRequiredView(AccessMixin, View):
self._provider = get_object_or_404(SAMLProvider, pk=application.provider_id) self._provider = get_object_or_404(SAMLProvider, pk=application.provider_id)
return self._provider return self._provider
def _has_access(self): def _has_access(self) -> bool:
"""Check if user has access to application""" """Check if user has access to application"""
policy_engine = PolicyEngine( policy_engine = PolicyEngine(
self.provider.application.policies.all(), self.request.user, self.request self.provider.application.policies.all(), self.request.user, self.request
@ -87,8 +89,8 @@ class LoginBeginView(AccessRequiredView):
source = request.POST source = request.POST
else: else:
source = request.GET source = request.GET
# Store these values now, because Django's login cycle won't preserve them.
# Store these values now, because Django's login cycle won't preserve them.
try: try:
request.session["SAMLRequest"] = source["SAMLRequest"] request.session["SAMLRequest"] = source["SAMLRequest"]
except (KeyError, MultiValueDictKeyError): except (KeyError, MultiValueDictKeyError):
@ -123,10 +125,9 @@ class LoginProcessView(AccessRequiredView):
Presents a SAML 2.0 Assertion for POSTing back to the Service Provider.""" Presents a SAML 2.0 Assertion for POSTing back to the Service Provider."""
# pylint: disable=unused-argument # pylint: disable=unused-argument
def get(self, request, application): def get(self, request: HttpRequest, application: str) -> HttpResponse:
"""Handle get request, i.e. render form""" """Handle get request, i.e. render form"""
LOGGER.debug("SAMLLoginProcessView", request=request, method="get") # User access gets checked in dispatch
# Check if user has access
if self.provider.application.skip_authorization: if self.provider.application.skip_authorization:
ctx = self.provider.processor.generate_response() ctx = self.provider.processor.generate_response()
# Log Application Authorization # Log Application Authorization
@ -148,10 +149,9 @@ class LoginProcessView(AccessRequiredView):
return HttpResponseBadRequest() return HttpResponseBadRequest()
# pylint: disable=unused-argument # pylint: disable=unused-argument
def post(self, request, application): def post(self, request, application: str) -> HttpResponse:
"""Handle post request, return back to ACS""" """Handle post request, return back to ACS"""
LOGGER.debug("SAMLLoginProcessView", request=request, method="post") # User access gets checked in dispatch
# Check if user has access
if request.POST.get("ACSUrl", None): if request.POST.get("ACSUrl", None):
# User accepted request # User accepted request
Event.new( Event.new(
@ -166,10 +166,10 @@ class LoginProcessView(AccessRequiredView):
relay_state=request.POST.get("RelayState"), relay_state=request.POST.get("RelayState"),
) )
try: try:
full_res = _generate_response(request, self.provider) return _generate_response(request, self.provider)
return full_res
except exceptions.CannotHandleAssertion as exc: except exceptions.CannotHandleAssertion as exc:
LOGGER.debug(exc) LOGGER.debug(exc)
return HttpResponseBadRequest()
class LogoutView(CSRFExemptMixin, AccessRequiredView): class LogoutView(CSRFExemptMixin, AccessRequiredView):