Skip to content
Snippets Groups Projects
  • Duncan Mortimer's avatar
    53609358
    Support for Django 1.6+ · 53609358
    Duncan Mortimer authored
    UNUSUABLE_PASSWORD has been replaced with UNUSABLE_PASSWORD_PREFIX and
    UNUSABLE_PASSWORD_SUFFIX, however, neither of these needs to be used as
    by not passing a password to the user create method you get an unusable
    password by default.
    53609358
    History
    Support for Django 1.6+
    Duncan Mortimer authored
    UNUSUABLE_PASSWORD has been replaced with UNUSABLE_PASSWORD_PREFIX and
    UNUSABLE_PASSWORD_SUFFIX, however, neither of these needs to be used as
    by not passing a password to the user create method you get an unusable
    password by default.
webauth_ldap.py 2.73 KiB
import ldap
import ldap.sasl
import logging
import re

from django.conf import settings
from django.contrib.auth.models import User, Group

logger = logging.getLogger(__name__)


class WebauthLDAPBackend(object):
    def __init__(self):
        self.ldap_endpoint = getattr(settings, 'WEBAUTH_LDAP_ENDPOINT',
                'ldap://ldap.oak.ox.ac.uk:389')

    def authenticate(self, username):
        user, _ = User.objects.get_or_create(username=username)
        auth = ldap.sasl.gssapi('')
        oakldap = ldap.initialize(self.ldap_endpoint)
        oakldap.start_tls_s()
        oakldap.sasl_interactive_bind_s('', auth)

        results = oakldap.search_s('ou=people,dc=oak,dc=ox,dc=ac,dc=uk',
                                   ldap.SCOPE_SUBTREE,
                                   '(oakPrincipal=krbPrincipalName=%s@OX.AC.UK,cn=OX.AC.UK,cn=KerberosRealms,dc=oak,dc=ox,dc=ac,dc=uk)' % username)

        if not results:
            return None
        person = results[0][1]

        for name, key in (('first_name', 'givenName'),
                          ('last_name', 'sn'),
                          ('email', 'mail')):
            try:
                setattr(user, name, person[key][0])
            except KeyError, e:
                setattr(user, name, '')
                logger.warning("User %s doesn't have a %s", username, key)

        oakgroups = self.get_groups(user, person)
        user.groups = set(user.groups.all()).union(oakgroups)
        
        user.backend = 'django_webauth.backends.webauth_ldap.WebauthLDAPBackend'

        user.save()
        return user

    def get_groups(self, user, person):
        groups = set('status:%s' % s for s in person['oakStatus'])
        for g in person.get('oakITSSFor', ()):
            match = re.match(r'oakGN=ITSS,oakUnitCode=(\w+),ou=units,dc=oak,dc=ox,dc=ac,dc=uk', g)
            if match:
                groups.add('itss:%s' % match.group(1))
            elif g == 'oakGN=ITSS,ou=oucscentral,dc=oak,dc=ox,dc=ac,dc=uk':
                groups.add('itss')
        for u in person.get('eduPersonOrgUnitDN', ()):
            match = re.match(r'oakUnitCode=(\w+),ou=units,dc=oak,dc=ox,dc=ac,dc=uk', u)
            if match:
                groups.add('affiliation:%s' % match.group(1))

        # As per http://www.oucs.ox.ac.uk/services/oak/sp/ldap/index.xml?ID=recommendations
        # if someone has an eduPersonAffiliation of 'member', they are a member
        # of the University
        if 'member' in person.get('eduPersonAffiliation'):
            groups.add('member')

        return set(Group.objects.get_or_create(name=name)[0] for name in groups)

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None