email authentification doesn't work using django-allauth

Question:

I installed django-allauth and set it up to use it for the internet registration and authentication backend in order to have an email confirmation at registration and sign up the users using their email instead of their username.

What is happening is that the registration works perfectly, the authentication using the email doesn’t work whereas it’s working with the username. I got the following error:

The e-mail address and/or password you specified are not correct.

Here my current configuration:

  • Django-allauth: 0.35.0
  • Django: 1.11
  • Python: 3.6.4
  • mysql: 15.1
# settings.py

SITE_ID = 1

DJANGO_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.sites',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
THIRD_PARTY_APPS = [
    'allauth',
    'allauth.account',
    'allauth.socialaccount',
]

AUTHENTIFICATION_BACKENDS = [
        'django.contrib.auth.backends.ModelBackend',
        'allauth.account.auth_backends.AuthenticationBackend',
]
LOGIN_REDIRECT_URL = 'main:home'
LOGOUT_REDIRECT_URL = 'main:home'

TEMPLATES = [
   {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            os.path.join(APPS_DIR, 'templates'),
        ],
        'OPTIONS': {
            'debug': DEBUG,
            'loaders': [
                'django.template.loaders.filesystem.Loader',
                'django.template.loaders.app_directories.Loader',
            ],
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.template.context_processors.media',
                'django.template.context_processors.i18n',
                'django.template.context_processors.static',
                'django.template.context_processors.tz',
                'django.contrib.messages.context_processors.messages',
            ],
       },
    },
]

ACCOUNT_AUTHENTICATION_METHOD = 'username_email'
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_EMAIL_VERIFICATION = 'mandatory'
ACCOUNT_CONFIRM_EMAIL_ON_GET = True
# url.py

urlpatterns = [
    # Django admin
    url(settings.ADMIN_URL, admin.site.urls),

    url(r'', include('main.urls')),
    url(r'^accounts/', include('allauth.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

I hope I gave all the useful information. I wonder if I missed a configuration issue or if there is a bug somewhere. If you need more information, please let me know, I will gladly provide my help on that matter.

Asked By: mattberjon

||

Answers:

After some thinking and research, I found a workaround by writing my own adapter as described in the documentation. It consists of rewriting the method save_user().

In order to proceed, you need first to tell your app where is the new adapter by editing the settings.py and adding the following line:

ACCOUNT_ADAPTER = 'yourproject.yourapp.file.classname'

Then create the adapter file such as yourproject/yourapp.file.py, in my case I called the file.py adapter.py and add the following code:

from allauth.account.adapter import DefaultAccountAdapter

class AccountAdapter(DefaultAccountAdapter):

    def save_user(self, request, user, form, commit=True):
        data = form.cleaned_data
        user.email = data.get('email')
        user.username = data.get('email')
        if 'password1' in data:
            user.set_password(data["password1"])
        else:
            user.set_unusable_password()
        self.populate_username(request, user)
        if commit:
            # Ability not to commit makes it easier to derive from
            # this adapter by adding
            user.save()
        return user

Basically, it’s really close to the actual method except I save the email as such as the username in the django system. You will need as well to edit the login.html template if you want to avoid confusion with your user and force the username field to display email.

To avoid any issues related to a malformed email address, you can then add a validator as described in the documentation.

# In validators.py

from django.core.validators import EmailValidator


custom_username_validators = [ASCIIUsernameValidator()]


# In settings.py

ACCOUNT_USERNAME_VALIDATORS = 'some.module.validators.custom_username_validators'
Answered By: mattberjon

Had same issue today, my solution was that I was missed the AUTHENTICATION_BACKENDS step when installing allauth.

Ensure you have the following in your settings.py

AUTHENTICATION_BACKENDS = (
    # Needed to login by username in Django admin, regardless of `allauth`
    "django.contrib.auth.backends.ModelBackend",
    # `allauth` specific authentication methods, such as login by e-mail
    "allauth.account.auth_backends.AuthenticationBackend"
)

See http://www.sarahhagstrom.com/2013/09/the-missing-django-allauth-tutorial for a helpful guide

And i noticed yours seems you had put it there but those are the reasons also but maybe you create a default adapter like https://stackoverflow.com/users/6771829/mattberjon as he said but i am sure mostimes its the authentication backend

Answered By: Favour Afenikhena