1

I have the following authentication for users in Django:

class EmailBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        UserModel = get_user_model()
        try:
            user = UserModel.objects.get(email=username)
        except UserModel.DoesNotExist:
            return None
        else:
            if user.check_password(password):
                return user
        return None

def register(request):
    if request.method == 'POST':
        form = UserRegisterForm(request.POST)
        if form.is_valid():
            form.save()
            username = form.cleaned_data.get('username')
            messages.success(request, f'Your account has been created! You are now able to log in')
            return redirect('login')
    else:
        form = UserRegisterForm()
    return render(request, 'users/register.html', {'form': form})

Users can log in using their Username or email but if the email or user name has a case sensitive letter it shows as an error:

Please enter the correct username and password. Note that both fields may be case-sensitive.

models.py

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)

forms.py

class UserRegisterForm(UserCreationForm):
    email = forms.EmailField()

    class Meta:
        model = User
        fields = ['username', 'email', 'password1', 'password2']

My question: How can authenticate users with case insensitive username or email:

A_K
  • 731
  • 3
  • 15
  • 40
  • have a look here: https://stackoverflow.com/questions/6797984/how-do-i-lowercase-a-string-in-python as a starting point >:) – Tomek Feb 03 '21 at 02:54

2 Answers2

2

You need to make it lower/upper case when registering the user.

def register(request):
    if request.method == 'POST':
        form = UserRegisterForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data.get('username')
            form.cleaned_data['username'] = username.lower()
            # do same for email if needed
            form.save()
            messages.success(request, f'Your account has been created! You are now able to log in')
            return redirect('login')
    else:
        form = UserRegisterForm()
    return render(request, 'users/register.html', {'form': form})

And also when authenticating the user check with the same case.

class EmailBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        UserModel = get_user_model()
        try:
            user = UserModel.objects.get(email=username.lower())
        except UserModel.DoesNotExist:
            return None
        else:
            if user.check_password(password):
                return user
        return None
Nahidur Rahman
  • 795
  • 1
  • 6
  • 17
  • the issue is when the user types in the name it shows error if he has any upper cases in the username or email. – A_K Feb 04 '21 at 01:23
  • Yeah, that's why you need to lower case username or email when registering the user, and when the user login you also lower case it while querying the user. By doing that whatever case(upper or lower) users type the issue will not arise as it was saved in lower case in DB and you are lower casing it when getting the user. – Nahidur Rahman Feb 04 '21 at 04:18
1

If you want to make the username/email case insensitive, I think a simple way to do it would be to update your view as follows:

def register(request):
    if request.method == 'POST':
        form = UserRegisterForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data.get('username').lower()
            form.save()
            messages.success(request, f'Your account has been created! You are now able to log in')
            return redirect('login')
    else:
        form = UserRegisterForm()
    return render(request, 'users/register.html', {'form': form})
brandonris1
  • 455
  • 3
  • 9