diff --git a/common/djangoapps/third_party_auth/saml.py b/common/djangoapps/third_party_auth/saml.py index 61f7e0d8f5..8b23c21d6f 100644 --- a/common/djangoapps/third_party_auth/saml.py +++ b/common/djangoapps/third_party_auth/saml.py @@ -2,6 +2,8 @@ Slightly customized python-social-auth backend for SAML 2.0 support """ import logging +from django.http import Http404 +from django.utils.functional import cached_property from social.backends.saml import SAMLAuth, OID_EDU_PERSON_ENTITLEMENT from social.exceptions import AuthForbidden, AuthMissingParameter @@ -22,12 +24,6 @@ class SAMLAuthBackend(SAMLAuth): # pylint: disable=abstract-method def setting(self, name, default=None): """ Get a setting, from SAMLConfiguration """ - if not hasattr(self, '_config'): - from .models import SAMLConfiguration - self._config = SAMLConfiguration.current() # pylint: disable=attribute-defined-outside-init - if not self._config.enabled: - from django.core.exceptions import ImproperlyConfigured - raise ImproperlyConfigured("SAML Authentication is not enabled.") try: return self._config.get_setting(name) except KeyError: @@ -35,14 +31,18 @@ class SAMLAuthBackend(SAMLAuth): # pylint: disable=abstract-method def auth_url(self): """ - Check that the request includes an 'idp' parameter before getting the - URL to which we must redirect in order to authenticate the user. + Check that SAML is enabled and that the request includes an 'idp' + parameter before getting the URL to which we must redirect in order to + authenticate the user. + raise Http404 if SAML authentication is disabled. raise AuthMissingParameter if the 'idp' parameter is missing. - - TODO: remove this method once the fix is merged upstream: - https://github.com/omab/python-social-auth/pull/821 """ + if not self._config.enabled: + log.error('SAML authentication is not enabled') + raise Http404 + # TODO: remove this check once the fix is merged upstream: + # https://github.com/omab/python-social-auth/pull/821 if 'idp' not in self.strategy.request_data(): raise AuthMissingParameter(self, 'idp') return super(SAMLAuthBackend, self).auth_url() @@ -61,3 +61,8 @@ class SAMLAuthBackend(SAMLAuth): # pylint: disable=abstract-method log.warning( "SAML user from IdP %s rejected due to missing eduPersonEntitlement %s", idp.name, expected) raise AuthForbidden(self) + + @cached_property + def _config(self): + from .models import SAMLConfiguration + return SAMLConfiguration.current() diff --git a/common/djangoapps/third_party_auth/tests/test_views.py b/common/djangoapps/third_party_auth/tests/test_views.py index 538c82eb46..29d14b065b 100644 --- a/common/djangoapps/third_party_auth/tests/test_views.py +++ b/common/djangoapps/third_party_auth/tests/test_views.py @@ -143,3 +143,9 @@ class SAMLAuthTest(SAMLTestCase): self.enable_saml() response = self.client.get(self.LOGIN_URL) self.assertEqual(response.status_code, 302) + + def test_login_disabled(self): + """ When SAML is not enabled, the login view should return 404 """ + self.enable_saml(enabled=False) + response = self.client.get(self.LOGIN_URL) + self.assertEqual(response.status_code, 404)