1User objects 2============ 3 4Authenticating against an external source is swell, but Django's auth module is 5tightly bound to a user model. When a user logs in, we have to create a model 6object to represent them in the database. Because the LDAP search is 7case-insensitive, the default implementation also searches for existing Django 8users with an iexact query and new users are created with lowercase usernames. 9See :meth:`~django_auth_ldap.backend.LDAPBackend.get_or_build_user` if you'd 10like to override this behavior. See 11:meth:`~django_auth_ldap.backend.LDAPBackend.get_user_model` if you'd like to 12substitute a proxy model. 13 14By default, lookups on existing users are done using the user model's 15:attr:`~django.contrib.auth.models.CustomUser.USERNAME_FIELD`. To lookup by a 16different field, use :setting:`AUTH_LDAP_USER_QUERY_FIELD`. When set, the 17username field is ignored. 18 19When using the default for lookups, the only required field for a user is the 20username. The default :class:`~django.contrib.auth.models.User` model can be 21picky about the characters allowed in usernames, so 22:class:`~django_auth_ldap.backend.LDAPBackend` includes a pair of hooks, 23:meth:`~django_auth_ldap.backend.LDAPBackend.ldap_to_django_username` and 24:meth:`~django_auth_ldap.backend.LDAPBackend.django_to_ldap_username`, to 25translate between LDAP usernames and Django usernames. You may need this, for 26example, if your LDAP names have periods in them. You can subclass 27:class:`~django_auth_ldap.backend.LDAPBackend` to implement these hooks; by 28default the username is not modified. :class:`~django.contrib.auth.models.User` 29objects that are authenticated by 30:class:`~django_auth_ldap.backend.LDAPBackend` will have an ``ldap_username`` 31attribute with the original (LDAP) username. 32:attr:`~django.contrib.auth.models.User.username` (or 33:meth:`~django.contrib.auth.models.AbstractBaseUser.get_username`) will, of 34course, be the Django username. 35 36.. note:: 37 38 Users created by :class:`~django_auth_ldap.backend.LDAPBackend` will have an 39 unusable password set. This will only happen when the user is created, so if 40 you set a valid password in Django, the user will be able to log in through 41 :class:`~django.contrib.auth.backends.ModelBackend` (if configured) even if 42 they are rejected by LDAP. This is not generally recommended, but could be 43 useful as a fail-safe for selected users in case the LDAP server is 44 unavailable. 45 46 47Populating Users 48---------------- 49 50You can perform arbitrary population of your user models by adding listeners to 51the :mod:`Django signal <django:django.dispatch>`: 52:data:`django_auth_ldap.backend.populate_user`. This signal is sent after the 53user object has been constructed (but not necessarily saved) and any configured 54attribute mapping has been applied (see below). You can use this to propagate 55information from the LDAP directory to the user object any way you like. If you 56need the user object to exist in the database at this point, you can save it in 57your signal handler or override 58:meth:`~django_auth_ldap.backend.LDAPBackend.get_or_build_user`. In either case, 59the user instance will be saved automatically after the signal handlers are run. 60 61If you need an attribute that isn't included by default in the LDAP search 62results, see :setting:`AUTH_LDAP_USER_ATTRLIST`. 63 64 65Easy Attributes 66--------------- 67 68If you just want to copy a few attribute values directly from the user's LDAP 69directory entry to their Django user, the setting, 70:setting:`AUTH_LDAP_USER_ATTR_MAP`, makes it easy. This is a dictionary that 71maps user model keys, respectively, to (case-insensitive) LDAP attribute 72names: 73 74.. code-block:: python 75 76 AUTH_LDAP_USER_ATTR_MAP = {"first_name": "givenName", "last_name": "sn"} 77 78Only string fields can be mapped to attributes. Boolean fields can be defined by 79group membership: 80 81.. code-block:: python 82 83 AUTH_LDAP_USER_FLAGS_BY_GROUP = { 84 "is_active": "cn=active,ou=groups,dc=example,dc=com", 85 "is_staff": ( 86 LDAPGroupQuery("cn=staff,ou=groups,dc=example,dc=com") 87 | LDAPGroupQuery("cn=admin,ou=groups,dc=example,dc=com") 88 ), 89 "is_superuser": "cn=superuser,ou=groups,dc=example,dc=com", 90 } 91 92Values in this dictionary may be simple DNs (as strings), lists or tuples of 93DNs, or :class:`~django_auth_ldap.config.LDAPGroupQuery` instances. Lists are 94converted to queries joined by ``|``. 95 96Remember that if these settings don't do quite what you want, you can always use 97the signals described in the previous section to implement your own logic. 98 99 100Updating Users 101-------------- 102 103By default, all mapped user fields will be updated each time the user logs in. 104To disable this, set :setting:`AUTH_LDAP_ALWAYS_UPDATE_USER` to ``False``. If 105you need to populate a user outside of the authentication process—for example, 106to create associated model objects before the user logs in for the first 107time—you can call :meth:`django_auth_ldap.backend.LDAPBackend.populate_user`. 108You'll need an instance of :class:`~django_auth_ldap.backend.LDAPBackend`, which 109you should feel free to create yourself. 110:meth:`~django_auth_ldap.backend.LDAPBackend.populate_user` returns the 111:class:`~django.contrib.auth.models.User` or `None` if the user could not be 112found in LDAP. 113 114.. code-block:: python 115 116 from django_auth_ldap.backend import LDAPBackend 117 118 user = LDAPBackend().populate_user("alice") 119 if user is None: 120 raise Exception("No user named alice") 121 122 123.. _ldap_user: 124 125Direct Attribute Access 126----------------------- 127 128If you need to access multi-value attributes or there is some other reason that 129the above is inadequate, you can also access the user's raw LDAP attributes. 130``user.ldap_user`` is an object with four public properties. The group 131properties are, of course, only valid if groups are configured. 132 133 * ``dn``: The user's distinguished name. 134 * ``attrs``: The user's LDAP attributes as a dictionary of lists of string 135 values. The dictionaries are modified to use case-insensitive keys. 136 * ``group_dns``: The set of groups that this user belongs to, as DNs. 137 * ``group_names``: The set of groups that this user belongs to, as simple 138 names. These are the names that will be used if 139 :setting:`AUTH_LDAP_MIRROR_GROUPS` is used. 140 141Python-ldap returns all attribute values as utf8-encoded strings. For 142convenience, this module will try to decode all values into Unicode strings. Any 143string that can not be successfully decoded will be left as-is; this may apply 144to binary values such as Active Directory's objectSid. 145