Skip to content

Conversation

@danidee10
Copy link

@danidee10 danidee10 commented Nov 11, 2025

Checklist

  • Local tests pass (ak test authentik/)
  • The code has been formatted (make lint-fix)

Initially, I started with a more complex Implementation which detected the password hash change in all cases but it felt a bit hacky as I had to use Queryset.update to avoid emitting a signal.

I switched to a simpler approach that uses model_utils.FieldTracker. It only detects changes when the audit middleware runs and register the signal handlers i.e It will not detect changes that happen outside the request/response cycle.

The rationale behind this is that anyone who changes the iterations/rounds of the hashers is probably an advanced user that knows that the hashes will be updated the next time django runs check_password and they shouldn't need an explicit event log

closes #17840

@netlify
Copy link

netlify bot commented Nov 11, 2025

Deploy Preview for authentik-storybook canceled.

Name Link
🔨 Latest commit 391a3d3
🔍 Latest deploy log https://app.netlify.com/projects/authentik-storybook/deploys/691f244fd6bde20008074897

@netlify
Copy link

netlify bot commented Nov 11, 2025

Deploy Preview for authentik-docs ready!

Name Link
🔨 Latest commit 391a3d3
🔍 Latest deploy log https://app.netlify.com/projects/authentik-docs/deploys/691f244f066fa80008383ca5
😎 Deploy Preview https://deploy-preview-18068--authentik-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link

netlify bot commented Nov 11, 2025

Deploy Preview for authentik-integrations canceled.

Name Link
🔨 Latest commit 391a3d3
🔍 Latest deploy log https://app.netlify.com/projects/authentik-integrations/deploys/691f244f1318270008396ef8

@codecov
Copy link

codecov bot commented Nov 11, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.92%. Comparing base (c11f3d9) to head (d3118c8).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #18068   +/-   ##
=======================================
  Coverage   92.92%   92.92%           
=======================================
  Files         869      871    +2     
  Lines       48040    48075   +35     
=======================================
+ Hits        44643    44676   +33     
- Misses       3397     3399    +2     
Flag Coverage Δ
e2e 45.20% <22.22%> (+0.03%) ⬆️
integration 23.12% <11.11%> (-0.07%) ⬇️
unit 91.08% <100.00%> (+0.01%) ⬆️
unit-migrate 91.13% <100.00%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

export COMPOSE_PROJECT_NAME="authentik-test-${AUTHENTIK_TAG}"

if [[ -v BUILD ]]; then
if [ -n "${BUILD:-}" ]; then
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When trying to test with docker. I discovered that this syntax wasn't POSIX compliant and didn't work on macos (with bash 3.2)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can confirm the same with zsh 5.9 (arm64-apple-darwin25.0)

Copy link
Member

@rissson rissson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@danidee10 fancy seeing you here! Thank you for the contribution!

Comment on lines 207 to 208
if isinstance(instance, User) and instance.tracker.has_changed("password"):
context["reason"] = PASSWORD_HASH_UPGRADE_REASON
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do we know this is not just the user changing their password?

Copy link
Author

@danidee10 danidee10 Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't know as there's no way to distinguish why the hash changed here
But I thought it might be acceptable since there's already an existing PASSWORD_SET event that tracks password changes. Thus, anyone looking at the event log can figure out why the hash changed.

I had a different approach here which shouldn't log the event (when the user changes their password) as it doesn't depend on the User model's post_save signal.

I guess it depends on how you answer these questions:
Should we track all password hash changes regardless of how they happened ? or
Should we only track password hash changes because Django changed the iterations of the hasher ?

@rissson rissson added this to the Release 2025.10.2 milestone Nov 12, 2025
@rissson rissson requested a review from BeryJu November 12, 2025 13:47
@BeryJu
Copy link
Member

BeryJu commented Nov 18, 2025

ideas from chatting with @rissson

  • check if we can override django to know when the password is upgraded
  • context manager for authenticate() call to add this to event since that's the only time this should be triggered

@danidee10
Copy link
Author

check if we can override django to know when the password is upgraded

That was my Initial approach by overriding User.check_password but I didn't like the fact that I had to disable the post_save signal. I've been thinking about it again and I think there's a better way to Implement it without disabling the signal entirely.

context manager for authenticate() call to add this to event since that's the only time this should be triggered
I'm less inclined towards this approach

It has more moving parts (We have to apply the context manager to all existing auth backends and future auth backends)
I also have some open questions about the Implementation:

  1. is the plan to get the context manager to attach some extra context so we can reuse the existing code in the audit middleware ? If yes then it's even more moving parts because the middleware runs before authenticate is called.
  2. Are we sending a new Event from the context manager ? If yes then we still have to find a way to disable the signal that's triggered in check_password.

I will go with the check if we can override django to know when the password is upgraded approach

@danidee10
Copy link
Author

danidee10 commented Nov 20, 2025

@BeryJu I went with Option 1 as stated earlier. I replaced model_utils.FieldTracker with a class attribute to track the password hash change. I also added a new test.

@BeryJu BeryJu requested review from melizeche and rissson November 20, 2025 14:46
@BeryJu BeryJu removed the request for review from authentik-bot November 20, 2025 14:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

Add reason for model_updated of a user after authentik upgrade

4 participants