I've written a custom authenticator which auths users based on their email address and not their username. This has broken logins at /admin, as it apparently doesn't allow an email to be used in the username field:

Is there a way I could get around this issue?
Here is the relevant login method from the admin app (unimportant detail elided):
def login(self, request):
from django.contrib.auth.models import User
# Check the password.
username = request.POST.get('username', None)
password = request.POST.get('password', None)
user = authenticate(username=username, password=password)
if user is None:
message = ERROR_MESSAGE
if username is not None and u'@' in username:
# Mistakenly entered e-mail address instead of username? Look it up.
try:
user = User.objects.get(email=username)
except (User.DoesNotExist, User.MultipleObjectsReturned):
message = _("Usernames cannot contain the '@' character.")
else:
if user.check_password(password):
message = _("Your e-mail address is not your username."
" Try '%s' instead.") % user.username
else:
message = _("Usernames cannot contain the '@' character.")
return self.display_login_form(request, message)
# The user data is correct; log in the user in and continue.
else:
if user.is_active and user.is_staff:
login(request, user)
return http.HttpResponseRedirect(request.get_full_path())
else:
return self.display_login_form(request, ERROR_MESSAGE)
login = never_cache(login)
See how it tries to authenticate with the POST data fields of username and password? Notice also, how they don't use a django Form to do authentication? This is purely based on using the built in login and authenticate methods of the auth contrib app. This means there isn't really an opportunity to change the form. Instead, you have to ensure that your custom authenticator is registered as an authentication backend.
AUTHENTICATION_BACKENDS = ('mysite.backends.EmailBackend',)
Since the built in admin login method only checks for the existence of an email address if the AUTH_BACKEND returns no user, it means you should be free to use the email address in the existing form. This should work, but if it doesn't (and you've already set the Auth Backend), below is an alternative method.
So, what you could do, is override the admin login template, and post to your own custom login view which uses your own authenticator.
To override the default login page:
cp [src dir]/django/django/contrib/admin/templates/admin/login.html [project root]/templates/admin/login.html
Next, you'll want to strip out the existing form action, and point it to your own view:
<form action="/custom/login" method="post" id="login-form">{% csrf_token %}
I'm assuming you already have a view that does authentication, so post directly to that, and do a redirect on success to the main admin site.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With