Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion authentik/core/api/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@
"""Set password for user"""
user: User = self.get_object()
try:
user.set_password(request.data.get("password"))
user.set_password(request.data.get("password"), request=request)

Check warning on line 588 in authentik/core/api/users.py

View check run for this annotation

Codecov / codecov/patch

authentik/core/api/users.py#L588

Added line #L588 was not covered by tests
user.save()
except (ValidationError, IntegrityError) as exc:
LOGGER.debug("Failed to set password", exc=exc)
Expand Down
3 changes: 1 addition & 2 deletions authentik/core/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,12 @@
self, request: HttpRequest, username: str | None, password: str | None, **kwargs: Any
) -> User | None:
try:

user = User._default_manager.get_by_natural_key(username)

except User.DoesNotExist:
# Run the default password hasher once to reduce the timing
# difference between an existing and a nonexistent user (#20760).
User().set_password(password)
User().set_password(password, request=request)

Check warning on line 52 in authentik/core/auth.py

View check run for this annotation

Codecov / codecov/patch

authentik/core/auth.py#L52

Added line #L52 was not covered by tests
return None

tokens = Token.filter_not_expired(
Expand Down
4 changes: 2 additions & 2 deletions authentik/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,13 +356,13 @@ def is_staff(self) -> bool:
"""superuser == staff user"""
return self.is_superuser # type: ignore

def set_password(self, raw_password, signal=True, sender=None):
def set_password(self, raw_password, signal=True, sender=None, request=None):
if self.pk and signal:
from authentik.core.signals import password_changed

if not sender:
sender = self
password_changed.send(sender=sender, user=self, password=raw_password)
password_changed.send(sender=sender, user=self, password=raw_password, request=request)
self.password_change_date = now()
return super().set_password(raw_password)

Expand Down
4 changes: 2 additions & 2 deletions authentik/events/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@ def on_invitation_used(sender, request: HttpRequest, invitation: Invitation, **_


@receiver(password_changed)
def on_password_changed(sender, user: User, password: str, **_):
def on_password_changed(sender, user: User, password: str, request: HttpRequest | None, **_):
"""Log password change"""
Event.new(EventAction.PASSWORD_SET).from_http(None, user=user)
Event.new(EventAction.PASSWORD_SET).from_http(request, user=user)


@receiver(post_save, sender=Event)
Expand Down
6 changes: 3 additions & 3 deletions authentik/sources/kerberos/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ def authenticate(self, request: HttpRequest, **kwargs):
if "@" in username:
username, realm = username.rsplit("@", 1)

user, source = self.auth_user(username, realm, **kwargs)
user, source = self.auth_user(request, username, realm, **kwargs)
if user:
self.set_method("kerberos", request, source=source)
return user
return None

def auth_user(
self, username: str, realm: str | None, password: str, **filters
self, request: HttpRequest, username: str, realm: str | None, password: str, **filters
) -> tuple[User | None, KerberosSource | None]:
sources = KerberosSource.objects.filter(enabled=True)
user = User.objects.filter(
Expand Down Expand Up @@ -76,7 +76,7 @@ def auth_user(
user=user_source_connection.user,
)
user_source_connection.user.set_password(
password, sender=user_source_connection.source
password, sender=user_source_connection.source, request=request
)
user_source_connection.user.save()
return user_source_connection.user, user_source_connection.source
Expand Down
8 changes: 5 additions & 3 deletions authentik/sources/ldap/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@
return None
for source in LDAPSource.objects.filter(enabled=True):
LOGGER.debug("LDAP Auth attempt", source=source)
user = self.auth_user(source, **kwargs)
user = self.auth_user(request, source, **kwargs)

Check warning on line 23 in authentik/sources/ldap/auth.py

View check run for this annotation

Codecov / codecov/patch

authentik/sources/ldap/auth.py#L23

Added line #L23 was not covered by tests
if user:
self.set_method("ldap", request, source=source)
return user
return None

def auth_user(self, source: LDAPSource, password: str, **filters: str) -> User | None:
def auth_user(
self, request: HttpRequest, source: LDAPSource, password: str, **filters: str
) -> User | None:
"""Try to bind as either user_dn or mail with password.
Returns True on success, otherwise False"""
users = User.objects.filter(**filters)
Expand All @@ -43,7 +45,7 @@
if source.password_login_update_internal_password:
# Password given successfully binds to LDAP, so we save it in our Database
LOGGER.debug("Updating user's password in DB", user=user)
user.set_password(password, sender=source)
user.set_password(password, sender=source, request=request)
user.save()
return user
# Password doesn't match
Expand Down
4 changes: 3 additions & 1 deletion authentik/stages/user_write/stage.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,9 @@ def update_user(self, user: User):
for key, value in data.items():
setter_name = f"set_{key}"
# Check if user has a setter for this key, like set_password
if hasattr(user, setter_name):
if key == "password":
user.set_password(value, request=self.request)
elif hasattr(user, setter_name):
setter = getattr(user, setter_name)
if callable(setter):
setter(value)
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/test_source_ldap_samba.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def test_sync_password(self):
# Ensure user has an unusable password directly after sync
self.assertFalse(user.has_usable_password())
# Auth (which will fallback to bind)
LDAPBackend().auth_user(source, password, username=username)
LDAPBackend().auth_user(None, source, password, username=username)
user.refresh_from_db()
# User should now have a usable password in the database
self.assertTrue(user.has_usable_password())
Expand Down
Loading