Răsfoiți Sursa

[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 11 luni în urmă
părinte
comite
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