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 ?

Hi @kwstarikas,

Did you know all the attributes that ldap has of and object?

I ask this, because I create a Django application, that login with my LDAP and in configuration i assigned a parameter in seetings.py after creating a custom fields user.
AUTH_LDAP_USER_ATTR_MAP = {
“first_name”: “givenName”,
“last_name”: “sn”,
“email”: “mail”,
“department”: “aaeAppAdd”
}

When i login, the user is added to the django user database, but in logs appears this message.

cn=username,ou=ou_c,o=aa does not have a value for the attribute aaeAppAdd.

thanks

You can find all the LDAP attributes by running a for loop in a specific variable, I don’t remember exactly what this variable is called, and how you manage your LDAP attributes, but I remember that I did that and I could use whatever attribute the LDAP response send me for my scopes.

please how did you get or show all the attributes of user from in the ldap?

I have similar situation that when I login django add the user in his database, but at the same time in django logs, appears that and attribute doesn’t exist

thanks

I believe this is one way to list all the attributes, once you have successfully connected to your LDAP server using settings.py.

from django_auth_ldap.backend import LDAPBackend
from pprint import pprint
ldapuser = LDAPBackend().populate_user("username")
pprint(ldapuser.ldap_user.attrs)

The attributes will depend on how your LDAP server was setup. In my case, I was able to get a list of a user’s groups using “groupmembership”.

ldapuser.ldap_user.attrs['groupmembership']

I also wanted to grant superuser access based on an LDAP group:

AUTH_LDAP_USER_FLAGS_BY_GROUP = {
"is_superuser": "cn=aaa,ou=bbb,o=ccc",
}

The alternative, possibly easier option, to find the attributes could be to simply use ldapsearch in Linux:

ldapsearch -x -h ldap-server.company.com mail=bob@company.com

Hope some of that points you in the right direction :slight_smile:

I would like to map some of the field available in my companies Active Directory to my Django Application like department, Job Title so on. I am using the Django_auth_ldap for backend authentication and it copies the data and updates the record in the Django application Database. Since, Django Auth User table does not support these attributes what will be your suggestions of doing it? Please let me know if you need any more information.

As with all other cases of customizing the User object, you have two choices:

  • Use a custom User model
  • Create a “profile” model

The choice between these is up to you. I don’t use Django_auth_ldap, so I can’t say whether one would be easier than the other, but either one should allow you to save those mapped fields. Also see User objects — django-auth-ldap 4.1.1.dev6+ga6e03c6.d20220907 documentation.