Since the goal is to "prevent that the users are populated in the Django admin site", setting AUTH_LDAP_ALWAYS_UPDATE_USER
to False
would not b what you want: that would stop LDAP authentication altogether for new users.
If your goal is to allow LDAP users to authenticate but not to automatically create a corresponding Django User model instance, you will need to customize the authentication backend to achieve this behavior.
For instance, custom subclass of LDAPBackend
:
from django_auth_ldap.backend import LDAPBackend
from django.contrib.auth import get_user_model
class CustomLDAPBackend(LDAPBackend):
def get_or_create_user(self, username, ldap_user):
"""
That must return a (User, created) 2-tuple for the given
LDAP user. You may use Django's built-in get_user_model()
if you wish.
"""
User = get_user_model()
user = None
created = False
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
pass # User will stay None
return (user, created)
In this customized get_or_create_user
method, it will only return a user object if it already exists in the Django database. If the user does not exist, it will return None
, effectively avoiding the automatic creation of a new user.
To apply this custom backend, you need to update AUTHENTICATION_BACKENDS
in your settings.py
, as illustrated in the installation page:
AUTHENTICATION_BACKENDS = [
'path.to.CustomLDAPBackend', # Replace with the actual Python path to your subclass
'django.contrib.auth.backends.ModelBackend',
]
With this setup, users who authenticate via LDAP will only be able to log in if they already have a corresponding user record in the Django database. The system will not automatically create a new Django user upon successful LDAP authentication.
I tried this, but after the LDAP user logged in, I checked in an admin user that the users are still populated in the Django admin site.
I created a backends.py
file inside an app called authentication.
AUTHENTICATION_BACKENDS = [ >'authentication.backends.CustomLDAPBackend', >'django.contrib.auth.backends.ModelBackend', ]
Your AUTHENTICATION_BACKENDS
setting appears to be correct, assuming that your CustomLDAPBackend
class is defined in a file named backends.py
within an app named authentication
. If the users are still being populated, one possibility is that the CustomLDAPBackend
is not being properly used. You can verify that it is being used by placing a debug log or a breakpoint in the get_or_create_user
method to see if it is being executed during the login process.
Add logging imports to your backends.py
:
import logging
logger = logging.getLogger(__name__)
Update the get_or_create_user
method to include debug logs:
def get_or_create_user(self, username, ldap_user):
User = get_user_model()
user = None
created = False
try:
user = User.objects.get(username=username)
logger.debug(f"User {username} exists in Django, proceed to login.")
except User.DoesNotExist:
logger.debug(f"User {username} does not exist in Django, will not be created.")
pass # User will stay None
return (user, created)
And make sure your Django logging settings can capture debug logs. Update your settings.py
if necessary:
LOGGING = {
# (your existing settings),
'loggers': {
# (your existing loggers),
'authentication.backends': {
'handlers': ['console'],
'level': 'DEBUG',
},
},
}
Run your project and try to log in using an LDAP account. Then, check your logs to make sure that your get_or_create_user
method is being called and see what it returns.
If after these steps you find that users are still being automatically created, then the issue might be elsewhere, possibly even outside the CustomLDAPBackend
.
For the LOGGING
in the settings.py
, do I enclose all my settings inside? I tried putting it below the LDAP configurations, but it returns ValueError: dictionary doesn't specify a version
.
The logger in the get_or_create_user
does not return anything in the console after a user has logged in.
The LOGGING
configuration in settings.py
is usually a separate dictionary that defines how logging should be handled across the application. You do not have to enclose your other settings within it.
A basic example to include in your settings.py
(that should work without conflicting with your LDAP settings) would be:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'root': {
'handlers': ['console'],
'level': 'WARNING',
},
'loggers': {
'django': {
'handlers': ['console'],
'level': 'DEBUG',
'propagate': True,
},
'authentication.backends': {
'handlers': ['console'],
'level': 'DEBUG',
},
},
}
Make sure to include this as its own top-level key-value pair in your settings.py
, not nested inside any other setting. That example sets up a basic logging configuration that outputs log messages to the console.
Also, the ValueError: dictionary does not specify a version
error occurs when the LOGGING
dictionary does not contain a 'version'
key. That is required as per the configuration schema.
If the logger in the get_or_create_user
method does not output anything, there are a few possibilities:
- The method is not being called, which could mean that your custom backend is not being used.
- There is an issue with your logging configuration.
After you have added the correct LOGGING
settings, try to log in again and see if the debug messages are printed to the console. That will help verify whether your custom backend is actually being used.