Mapping LDAP attributes to extended User model

Hi all,

I’m trying to map LDAP attributes to a Profile model I’ve created but the fields aren’t being populated as I was hoping. LDAP authentication and AUTH_LDAP_USER_FLAGS_BY_GROUP are both working for reference. The first_name attribute maps correctly but only to the User model, not my Profile model. The same behaviour would apply if I renamed sn to last_name, uid to username and mail to email as those are what Django are expecting but all other fields are ignored.

Here’s my code:

settings.py

AUTH_LDAP_USER_ATTR_MAP = {
    "uid": "uid",
    "first_name": "givenName",
    "sn": "sn",
    "mail": "mail",
    "department": "CardiffJCCSTransDept",
    "userType": "CardiffJCCSTransType",
    "uidNumber": "uidNumber",
    "gidNumber": "gidNumber",
    "telephoneNumber": "telephoneNumber",
}

models.py

class Profile(Model):
    user = OneToOneField(User, on_delete=CASCADE)
    uid = CharField(max_length=254)
    first_name = CharField(max_length=254)    # will change back to givenName
    sn = CharField(max_length=254)
    mail = EmailField(max_length=254)
    department = CharField(max_length=254, null=True)
    userType = CharField(max_length=254, null=True)
    uidNumber = IntegerField(null=True)
    gidNumber = IntegerField(null=True)
    telephoneNumber = CharField(max_length=254)

def create_user_profile(sender, instance, created, **kwargs):
    Profile.objects.get_or_create(user=instance)

post_save.connect(create_user_profile, sender=User)

When a user logs in, both the User and Profile object’s are created but the Profile object has an empty record set (excluding id and user_id).

login output:

search_s('o=CF', 2, '(uid=%(user)s)') returned 1 objects: cn=sapcs10,ou=bla,ou=bla,o=bla
Creating Django user sapcs10
Populating Django user sapcs10

cn=sapcs10,ou=bla,ou=bla,o=bla is a member of cn=groupname 
[redacted multiple checks]

Returns first_name as expected:

lu = User.objects.get(username="sapcs10")
lu.profile.user.first_name

All return empty strings:

lu.profile.first_name
lu.profile.uid
prof = Profile.objects.get(id=8)
prof.uid

list(Profile.objects.values()[4:5])
[{'id': 11,
  'user_id': 31,
  'uid': '',
  'first_name': '',
  'sn': '',
  'mail': '',
  'department': None,
  'userType': None,
  'uidNumber': None,
  'gidNumber': None,
  'telephoneNumber': ''}]

LDAP Backend:

user = LDAPBackend().populate_user("sapcs10")
user.ldap_user.dn
Out:
cn=sapcs10,ou=bla,ou=bla,o=bla

The aim ultimately is to be able to access these attributes from the admin interface and within views. Any help is very much appreciated!

I can see in this method where you’re creating the profile object, but you don’t show any code where you assign the ldap data to that object. Where is that being done?

1 Like

Well don’t I feel stupid. It’s working in less than a few minutes! Thanks for your help again :slight_smile: I looked everywhere for a solution or example - clearly spent too much time concerned with with wrong things.

For those who may look at this thread, you can access the attributes as follows:

user=instance,
uid=instance.uid,
...

It is possible to use LDAPS instead of LDAP ?

Yep, I’m using LDAPS. Make sure you add the LDAP certificate to the certificate store (https://manuals.gfi.com/en/kerio/connect/content/server-configuration/ssl-certificates/adding-trusted-root-certificates-to-the-server-1605.html)

settings.py

ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
AUTH_LDAP_SERVER_URI = "ldaps://ldapserver.fake"

I couldn’t seem to set the options above using the AUTH_ directives but this worked for me on Django 3. I found using a Jupyter notebook (python manage.py shell_plus --notebook) very useful for troubleshooting.

how can you check what attributes ldap user object has ?