Skip to content

[BUG] Unhandled UserNotFound during LDAP group membership check causes 500 error #3871

@lunkwill42

Description

@lunkwill42

Describe the bug

When a user successfully authenticates via LDAP bind but cannot be found by DN search during the subsequent group membership verification, an unhandled UserNotFound exception causes a 500 Internal Server Error.

In ldap.authenticate(), the UserNotFound exception is caught during user.bind() (line 154), but not during the group membership check that follows. When require_group is configured, user.is_group_member() calls self.get_user_dn(), which may call search_dn(). If the LDAP search returns no results for the user, UserNotFound is raised and propagates unhandled all the way up to Django's error handler.

This can happen when the LDAP bind uses a suffix-based method (so the DN is never resolved during bind), and the subsequent DN search during group membership verification fails to find the user.

To Reproduce

  1. Configure NAV with LDAP authentication using a suffix for binding
  2. Configure require_group to require group membership verification
  3. Configure lookupmethod=search
  4. Have a user who can authenticate via bind but whose DN search returns no results (e.g. because search_dn() rebinds as manager, changing the connection state)
  5. Attempt to log in
  6. Observe a 500 error: UserNotFound at /index/login/

Expected behavior

If a user cannot be found during group membership verification, the login should fail gracefully with an "invalid credentials" message, not crash with a 500 error.

Tracebacks

Traceback (most recent call last):
  File "django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "nav/web/webfront/views.py", line 356, in login
    return do_login(request)
  File "nav/web/webfront/views.py", line 403, in do_login
    account = authenticate(request, username=username, password=password)
  File "django/contrib/auth/__init__.py", line 77, in authenticate
    user = backend.authenticate(request, **credentials)
  File "nav/web/auth/ldap_auth_backend.py", line 70, in authenticate
    if not (ldap_user := self._ldap_authenticate(username, password)):
  File "nav/web/auth/ldap_auth_backend.py", line 93, in _ldap_authenticate
    ldap_user = ldap.authenticate(username, password)
  File "nav/web/auth/ldap.py", line 163, in authenticate
    if user.is_group_member(group_dn):
  File "nav/web/auth/ldap.py", line 314, in is_group_member
    user_dn = self.get_user_dn()
  File "nav/web/auth/ldap.py", line 238, in get_user_dn
    self.user_dn, self.username = self.search_dn()
  File "nav/web/auth/ldap.py", line 269, in search_dn
    raise UserNotFound(filter_)
nav.web.auth.ldap.UserNotFound: User object was not found: (sAMAccountName=rudolf)

Environment

  • NAV version: 5.17.1

Additional context

The UserNotFound exception is already handled during the user.bind() phase of authenticate(), but the same exception can also be raised during the group membership and entitlement verification phases that follow. These post-bind code paths need the same exception handling.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions