Selaa lähdekoodia

[django] fixes for django-saml infinite redirect error

There were two issues
1. saml urls needed to be made accessible without auth
2. and without csrf.
Amit Srivastava 3 kuukautta sitten
vanhempi
commit
8d5eb8292f

+ 3 - 0
desktop/core/src/desktop/settings.py

@@ -581,8 +581,11 @@ SAML_AUTHENTICATION = 'libsaml.backend.SAML2Backend' in AUTHENTICATION_BACKENDS
 if SAML_AUTHENTICATION:
   from libsaml.saml_settings import *  # noqa: F403
   INSTALLED_APPS.append('libsaml')
+  INSTALLED_APPS.append('djangosaml2')
   LOGIN_URL = '/saml2/login/'
   SESSION_EXPIRE_AT_BROWSER_CLOSE = True
+  # Add required middleware for djangosaml2 1.9.3+
+  MIDDLEWARE.append('djangosaml2.middleware.SamlSessionMiddleware')
 
 # Middleware classes.
 for middleware in desktop.conf.MIDDLEWARE.get():

+ 3 - 3
desktop/libs/libsaml/src/libsaml/backend.py

@@ -32,7 +32,7 @@ from desktop.auth.backend import force_username_case, rewrite_user
 from desktop.conf import AUTH
 from desktop.lib.django_util import nonce_attribute
 from libsaml import conf, metrics
-from useradmin.models import User, UserProfile, get_default_user_group, get_profile
+from useradmin.models import get_default_user_group, get_profile, User, UserProfile
 
 LOG = logging.getLogger()
 
@@ -56,7 +56,7 @@ class SAML2Backend(_Saml2Backend):
     """
     return force_username_case(main_attribute)
 
-  def is_authorized(self, attributes, attribute_mapping):
+  def is_authorized(self, attributes, attribute_mapping, user=None, session_info=None):
     """Hook to allow custom authorization policies based on user belonging to a list of SAML groups."""
     LOG.debug('is_authorized() attributes = %s' % attributes)
     LOG.debug('is_authorized() attribute_mapping = %s' % attribute_mapping)
@@ -133,6 +133,6 @@ class SAML2Backend(_Saml2Backend):
         user = User.objects.get(username__iexact=username)
       else:
         user = User.objects.get(username=username)
-    except User.DoesNotExist as e:
+    except User.DoesNotExist:
       user = None
     return user

+ 15 - 25
desktop/libs/libsaml/src/libsaml/urls.py

@@ -15,7 +15,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import sys
 import logging
 
 from django.urls import re_path
@@ -23,34 +22,25 @@ from django.urls import re_path
 LOG = logging.getLogger()
 
 try:
-  from djangosaml2 import views as djangosaml2_views
+  from libsaml.views import AssertionConsumerServiceView, EchoAttributesView, LoginView, LogoutView, MetadataView
 
-  from libsaml import views as libsaml_views
-except ImportError:
-  LOG.warning('djangosaml2 module not found')
-  djangosaml2_views = None
-
-try:
-  from djangosaml2.views import logout_service_post
-except ImportError:
-  # We are on an older version of djangosaml2
-  logout_service_post = None
-
-
-if djangosaml2_views is not None:
   urlpatterns = [
-    re_path(r'^logout/$', djangosaml2_views.LogoutView.as_view(), name='saml2_logout')
+    re_path(r'^logout/$', LogoutView.as_view(), name='saml2_logout'),
+    re_path(r'^ls/$', LogoutView.as_view(), name='saml2_ls'),
+    re_path(r'^acs/$', AssertionConsumerServiceView.as_view(), name='saml2_acs'),
+    re_path(r'^login/$', LoginView.as_view(), name='saml2_login'),
+    re_path(r'^metadata/$', MetadataView.as_view(), name='saml2_metadata'),
+    re_path(r'^test/$', EchoAttributesView.as_view())
   ]
 
-  urlpatterns += [
-    re_path(r'^ls/$', libsaml_views.LogoutView.as_view(), name='saml2_ls'),
-    re_path(r'^acs/$', libsaml_views.CustomAssertionConsumerServiceView.as_view(), name='saml2_acs'),
-    re_path(r'^login/$', libsaml_views.LoginView.as_view(), name='saml2_login'),
-    re_path(r'^metadata/$', libsaml_views.MetadataView.as_view(), name='saml2_metadata'),
-    re_path(r'^test/$', libsaml_views.EchoAttributesView.as_view())
-  ]
+  try:
+    from libsaml.views import LogoutServicePostView
 
-  if logout_service_post is not None:
     urlpatterns += [
-      re_path(r'^ls/post/$', libsaml_views.LogoutServicePostView.as_view(), name='saml2_ls_post')
+      re_path(r'^ls/post/$', LogoutServicePostView.as_view(), name='saml2_ls_post')
     ]
+  except ImportError:
+    # We are on an older version of djangosaml2
+    pass
+except ImportError:
+  LOG.warning('djangosaml2 module not found')

+ 9 - 31
desktop/libs/libsaml/src/libsaml/views.py

@@ -14,40 +14,18 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-from django.views.decorators.csrf import csrf_exempt
-from django.views.decorators.http import require_POST
 from djangosaml2.views import AssertionConsumerServiceView, EchoAttributesView, LoginView, LogoutView, MetadataView
 
+LoginView.dispatch.login_notrequired = True
+EchoAttributesView.dispatch.login_notrequired = True
+MetadataView.dispatch.login_notrequired = True
+LogoutView.dispatch.login_notrequired = True
+AssertionConsumerServiceView.dispatch.login_notrequired = True
+
 try:
   from djangosaml2.views import LogoutServicePostView
+
+  LogoutServicePostView.dispatch.login_notrequired = True
 except ImportError:
   # We are on an older version of djangosaml2
-  LogoutServicePostView = None
-
-import libsaml.conf
-
-
-# Customize AssertionConsumerServiceView
-class CustomAssertionConsumerServiceView(AssertionConsumerServiceView):
-  def dispatch(self, request, *args, **kwargs):
-    username_source = libsaml.conf.USERNAME_SOURCE.get().lower()
-    return super().dispatch(request, *args, **kwargs)
-
-# Expose the views
-
-
-login = LoginView
-echo_attributes = EchoAttributesView
-metadata = MetadataView
-assertion_consumer_service = CustomAssertionConsumerServiceView
-logout_service = LogoutView
-logout_service_post = LogoutServicePostView
-
-__all__ = ['login', 'echo_attributes', 'assertion_consumer_service', 'metadata', 'logout_service', 'logout_service_post']
-
-# Set login_notrequired attribute
-for view in [LogoutView, LoginView, EchoAttributesView, AssertionConsumerServiceView, MetadataView]:
-  setattr(view, 'login_notrequired', True)
-
-if LogoutServicePostView is not None:
-  setattr(LogoutServicePostView, 'login_notrequired', True)
+  pass