diff --git a/userportal/authentication.py b/userportal/authentication.py index 9bc37cb..199a07c 100644 --- a/userportal/authentication.py +++ b/userportal/authentication.py @@ -1,19 +1,34 @@ -from djangosaml2.backends import Saml2Backend from django.contrib.auth.backends import RemoteUserBackend +from django.conf import settings +try: + from djangosaml2.backends import Saml2Backend -class staffSaml2Backend(Saml2Backend): - """This will add/remove the is_staff attribute from the user as appropriate.""" - def _update_user(self, user, attributes: dict, attribute_mapping: dict, force_save: bool = False): - if 'eduPersonAffiliation' in attributes: - if 'staff' in attributes['eduPersonAffiliation']: - user.is_staff = True - else: - user.is_staff = False - user.first_name = attributes['givenName'][0] - user.last_name = attributes['sn'][0] - force_save = True - return super()._update_user(user, attributes, attribute_mapping, force_save) + class staffSaml2Backend(Saml2Backend): + """This will add/remove the is_staff attribute from the user as appropriate.""" + def _update_user(self, user, attributes: dict, attribute_mapping: dict, force_save: bool = False): + # figure out if user is active (i.e. can login) + user.is_active = True + for attribute, value in settings.SAML_CONFIG['required_access_attributes']: + if attribute not in attributes or value not in attributes[attribute]: + user.is_active = False + break + + # figure out if user is staff + user.is_staff = False + for attribute, value in settings.SAML_CONFIG['staff_attributes']: + if attribute in attributes and value in attributes[attribute]: + user.is_staff = True + break + + user.first_name = attributes['givenName'][0] + user.last_name = attributes['sn'][0] + force_save = True + return super()._update_user(user, attributes, attribute_mapping, force_save) + + +except ImportError: + pass class staffRemoteUserBackend(RemoteUserBackend): @@ -32,3 +47,29 @@ def configure_user(self, request, user, created=True): user.is_staff = False user.save() return user + + +try: + from django_auth_ldap.backend import LDAPBackend + + class staffLdapBackend(LDAPBackend): + def get_or_build_user(self, username, ldap_user): + user, built = super().get_or_build_user(username, ldap_user) + + # figure out if user is active (i.e. can login) + user.is_active = True + for attribute, value in settings.LDAP_CONFIG['required_access_attributes']: + if attribute not in ldap_user.attrs.data or value not in ldap_user.attrs.data[attribute]: + user.is_active = False + break + + user.is_staff = False + for attribute, value in settings.LDAP_CONFIG['staff_attributes']: + if attribute in ldap_user.attrs.data and value in ldap_user.attrs.data[attribute]: + user.is_staff = True + + return user, built + + +except ImportError: + pass diff --git a/userportal/settings/10-base.py b/userportal/settings/10-base.py index 8eab4bc..e56a61b 100644 --- a/userportal/settings/10-base.py +++ b/userportal/settings/10-base.py @@ -152,6 +152,8 @@ LDAP_BASE_DN = 'dc=computecanada,dc=ca' +LDAP_CONFIG = {} + LOGIN_REDIRECT_URL = '/' # Set to DEMO to True to enable demo mode with anonymized data diff --git a/userportal/settings/40-saml.py b/userportal/settings/40-saml.py index f55f36b..f566d97 100644 --- a/userportal/settings/40-saml.py +++ b/userportal/settings/40-saml.py @@ -64,4 +64,11 @@ 'key_file': '/opt/private.key', # private part 'cert_file': '/opt/public.cert', # public part }], -} \ No newline at end of file + # Use this to define if the user can login + 'required_access_attributes': [], + + # Use this to assign the staff role based on attributes returned by SAML + 'staff_attributes': [ + ('eduPersonAffiliation', 'staff') + ] +}