Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUG: Setting AXES_USERNAME_FORM_FIELD to a custom value fails to fill the username field for AccessAttempt #1159

Open
jur-clerkx opened this issue Jan 18, 2024 · 3 comments

Comments

@jur-clerkx
Copy link

Describe the bug
In our project, we have set the AXES_USERNAME_FORM_FIELD to a custom value. When doing this, AccessAttempt in the database doesn't get a username set, this stays None.

After a quick debug, it showed that there is a call being made where the credentials are given. However, in the credentials dict, the username is stored in a field named username in stead of the value set in AXES_USERNAME_FORM_FIELD. Since the code tries to fetch the username based on the name in the settings, this will return None. Assumption for now is that this were it goes wrong.

To Reproduce
Steps to reproduce the behavior:

  1. Create a custom login form with a username field that has a custom name (e.g. auth-username)
  2. Set the AXES_USERNAME_FORM_FIELD to auth-username
  3. Do a failed login attempt
  4. The username field on the AccessAttempt will be empty.

Expected behavior
The username field on the AccessAttempt model is filled with the correct username.

Your environment
python version: 3.8.18
django version: 3.2.23
django-axes version: 6.3.0
Operating system: Mac OS

Additional context
What was interesting was that the credentials that were shown in the debugger was:
username: username filled in the form
password: ***********************

Possibly this conflicts with the logging implementation.

Possible implementation
Probably an easy bugfix where username is used in stead of the value set in AXES_USERNAME_FORM_FIELD

@jur-clerkx jur-clerkx added the bug label Jan 18, 2024
@jur-clerkx
Copy link
Author

So after some digging, it turns out that the code tries to fetch the username out of the Django login failed signal by using the AXES_USERNAME_FORM_FIELD as key. However, in our case, Django always uses the username key. Probably need to use the USERNAME_FIELD setting here?

@aleksihakli
Copy link
Member

Good catch. Would someone like to open a PR that changes the username field to a the more appropriate AXES_USERNAME_FORM_FIELD or USERNAME_FIELD value?

@jur-clerkx
Copy link
Author

I managed to trace it down to where the code conflicts with the data that is sent by the the Django user_login_failed signal:

username = get_client_username(request, credentials)

The get_client_username method will try to fetch the username from the credentials using the AXES_USERNAME_FORM_FIELD setting. However, the Django signal will use the regular name of the field used as username (username, e-mail etc).
I'll try to make a PR to fix this, probably by just preferring to look in the request for the username in stead of the credentials.

For people who are also having this issue, you can implement a workaround by using the AXES_USERNAME_CALLABLE setting:

AXES_USERNAME_CALLABLE = lambda request, _: request.POST.get("<your username field>", None)  # noqa

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants