I want to create a Google Login authentication method in my Django project. So, when a user visits my website for the first time, it will create a new user in my database and then login that user. In case a user with this email address already exists, that user will simply log in.
The first part of my goal works as expected (when a user visits my website for the first time, it will create a new user in my database and then login that user), but If I'm trying to log in as an existing user, django-allauth redirects me to /accounts/social/signup/
I've tried to fix it with a CustomSocialAccountAdapter, but it didn't really help me. Could you help me please to resolve my problem?
Here is my settings.py
:
# allauth
AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.ModelBackend",
"allauth.account.auth_backends.AuthenticationBackend",
]
SOCIALACCOUNT_PROVIDERS = {
"google": {
"APP": {
"client_id": os.environ.get("GOOGLE_CLIENT_ID", ""),
"secret": os.environ.get("GOOGLE_CLIENT_SECRET", ""),
},
"SCOPE": [
"profile",
"email",
],
"AUTH_PARAMS": {
"access_type": "offline",
},
},
}
ACCOUNT_LOGIN_REDIRECT_URL = "home"
ACCOUNT_LOGOUT_REDIRECT_URL = "home"
SOCIALACCOUNT_LOGIN_ON_GET = True
SOCIALACCOUNT_LOGOUT_ON_GET = True
ACCOUNT_AUTHENTICATION_METHOD = "email"
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_USER_MODEL_USERNAME_FIELD = None
SOCIALACCOUNT_AUTO_SIGNUP = True
ACCOUNT_LOGOUT_ON_GET = True
SOCIALACCOUNT_ADAPTER = "user.adapters.CustomSocialAccountAdapter"
My adapters.py
:
class CustomSocialAccountAdapter(DefaultSocialAccountAdapter):
def pre_social_login(self, request, sociallogin):
user = sociallogin.user
if not CustomUser.objects.filter(email=user.email).exists():
extra_data = sociallogin.account.extra_data
user.first_name = extra_data.get('given_name')
user.last_name = extra_data.get('family_name')
user.is_active = True
user.save()
else:
perform_login(request, user, 'none')
return super().pre_social_login(request, sociallogin)
My HTML code:
<a
class="login-social__link"
href="{% provider_login_url 'google' process='login' method='oauth2'>
<svg class="login__icon login-google">
<use
xlink:href="{% static 'images/sprite-icons.svg' %}#icon-google"
></use>
</svg>
</a>
I just modified adapters.py
like so:
from allauth.account.models import EmailAddress
def pre_social_login(self, request, sociallogin):
try:
user = CustomUser.objects.get(email=sociallogin.user.email)
sociallogin.connect(request, user)
email_address, created = EmailAddress.objects.get_or_create(user=user, email=user.email)
if not email_address.verified:
email_address.verified = True
email_address.primary = True
email_address.save()
...
except CustomUser.DoesNotExist:
...
When a user tries to login via a social account and that social account's email matches an email already in the database, django-allauth attempts to link the social account to the existing user account. If it cannot do so automatically (for instance, due to missing or mismatched data), it redirects to the signup page as a fallback.