providers/saml: fix users being able to authenticate without audit logs being created

This commit is contained in:
Jens Langhammer 2020-02-24 14:40:12 +01:00
parent 484dd6de09
commit 22838e66fe
5 changed files with 18 additions and 51 deletions

View File

@ -10,7 +10,8 @@ class ApplicationForm(forms.ModelForm):
"""Application Form""" """Application Form"""
provider = forms.ModelChoiceField( provider = forms.ModelChoiceField(
queryset=Provider.objects.all().order_by('pk').select_subclasses(), required=False queryset=Provider.objects.all().order_by("pk").select_subclasses(),
required=False,
) )
class Meta: class Meta:

View File

@ -231,7 +231,6 @@ class PasswordResetView(View):
login(request, nonce.user) login(request, nonce.user)
nonce.delete() nonce.delete()
messages.success( messages.success(
request, request, _(("Temporarily authenticated, please change your password")),
_(("Temporarily authenticated with Nonce, " "please change your password")),
) )
return redirect("passbook_core:user-change-password") return redirect("passbook_core:user-change-password")

View File

@ -12,7 +12,7 @@ LOGGER = get_logger()
class SentryIgnoredException(Exception): class SentryIgnoredException(Exception):
"""Base Class for all errors that are supressed, and not sent to sentry.""" """Base Class for all errors that are suppressed, and not sent to sentry."""
def before_send(event, hint): def before_send(event, hint):

View File

@ -16,9 +16,9 @@ urlpatterns = [
"<slug:application>/login/", views.LoginBeginView.as_view(), name="saml-login" "<slug:application>/login/", views.LoginBeginView.as_view(), name="saml-login"
), ),
path( path(
"<slug:application>/login/process/", "<slug:application>/login/authorize/",
views.LoginProcessView.as_view(), views.AuthorizeView.as_view(),
name="saml-login-process", name="saml-login-authorize",
), ),
path("<slug:application>/logout/", views.LogoutView.as_view(), name="saml-logout"), path("<slug:application>/logout/", views.LogoutView.as_view(), name="saml-logout"),
path( path(

View File

@ -91,14 +91,14 @@ class LoginBeginView(AccessRequiredView):
request.session["RelayState"] = source.get("RelayState", "") request.session["RelayState"] = source.get("RelayState", "")
return redirect( return redirect(
reverse( reverse(
"passbook_providers_saml:saml-login-process", "passbook_providers_saml:saml-login-authorize",
kwargs={"application": application}, kwargs={"application": application},
) )
) )
class LoginProcessView(AccessRequiredView): class AuthorizeView(AccessRequiredView):
"""Processor-based login continuation. """Ask the user for authorization to continue to the SP.
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."""
def handle_redirect( def handle_redirect(
@ -131,9 +131,10 @@ class LoginProcessView(AccessRequiredView):
try: try:
# application.skip_authorization is set so we directly redirect the user # application.skip_authorization is set so we directly redirect the user
if self.provider.application.skip_authorization: if self.provider.application.skip_authorization:
LOGGER.debug("skipping authz", application=self.provider.application)
return self.post(request, application) return self.post(request, application)
self.provider.processor.init_deep_link(request) self.provider.processor.can_handle(request)
params = self.provider.processor.generate_response() params = self.provider.processor.generate_response()
return render( return render(
@ -166,7 +167,7 @@ class LoginProcessView(AccessRequiredView):
"""Handle post request, return back to ACS""" """Handle post request, return back to ACS"""
# User access gets checked in dispatch # User access gets checked in dispatch
# we get here when skip_authorization is False, and after the user accepted # we get here when skip_authorization is True, and after the user accepted
# the authorization form # the authorization form
self.provider.processor.can_handle(request) self.provider.processor.can_handle(request)
saml_params = self.provider.processor.generate_response() saml_params = self.provider.processor.generate_response()
@ -268,45 +269,11 @@ class DescriptorDownloadView(AccessRequiredView):
class InitiateLoginView(AccessRequiredView): class InitiateLoginView(AccessRequiredView):
"""IdP-initiated Login""" """IdP-initiated Login"""
def handle_redirect(
self, params: SAMLResponseParams, skipped_authorization: bool
) -> HttpResponse:
"""Handle direct redirect to SP"""
# Log Application Authorization
Event.new(
EventAction.AUTHORIZE_APPLICATION,
authorized_application=self.provider.application,
skipped_authorization=skipped_authorization,
).from_http(self.request)
return render(
self.request,
"saml/idp/autosubmit_form.html",
{
"url": params.acs_url,
"attrs": {
"SAMLResponse": params.saml_response,
"RelayState": params.relay_state,
},
},
)
# pylint: disable=unused-argument
def get(self, request: HttpRequest, application: str) -> HttpResponse: def get(self, request: HttpRequest, application: str) -> HttpResponse:
"""Initiates an IdP-initiated link to a simple SP resource/target URL.""" """Initiates an IdP-initiated link to a simple SP resource/target URL."""
self.provider.processor.is_idp_initiated = True return redirect(
self.provider.processor.init_deep_link(request) reverse(
params = self.provider.processor.generate_response() "passbook_providers_saml:saml-login-authorize",
kwargs={"application": application},
# IdP-initiated Login Flow )
if self.provider.application.skip_authorization:
return self.handle_redirect(params, True)
return render(
request,
"saml/idp/login.html",
{
"saml_params": params,
"provider": self.provider,
"title": "Authorize Application",
},
) )