Introduction
Social authentication lets users log in with their existing Google, GitHub, or Facebook accounts instead of creating yet another username and password. django-allauth is the most popular package for adding social login to Django, supporting over 80 providers.
Key Concepts
django-allauth: A comprehensive Django package for authentication, registration, and social login.
SocialApp: Model storing provider credentials (client ID and secret).
Provider: A third-party service (Google, GitHub, etc.) that authenticates users.
Callback URL: The URL the provider redirects to after authentication.
SOCIALACCOUNT_PROVIDERS: Setting to configure scopes, parameters, and credentials for each provider.
Real World Context
A developer tools startup adding "Login with GitHub" saw a 35% increase in signups because developers prefer not to create new accounts. django-allauth handles the OAuth flow, user creation, and account linking, so the team shipped the feature in a day instead of building OAuth from scratch.
Deep Dive
Allow users to log in with their existing accounts from Google, GitHub, Facebook, and many other providers.
Installing django-allauth
bashpip install django-allauth
Basic Configuration
python# settings.py INSTALLED_APPS = [ 'django.contrib.sites', # ... 'allauth', 'allauth.account', 'allauth.socialaccount', # Providers 'allauth.socialaccount.providers.google', 'allauth.socialaccount.providers.github', 'allauth.socialaccount.providers.facebook', ] MIDDLEWARE = [ # ... 'allauth.account.middleware.AccountMiddleware', ] AUTHENTICATION_BACKENDS = [ 'django.contrib.auth.backends.ModelBackend', 'allauth.account.auth_backends.AuthenticationBackend', ] SITE_ID = 1 # Allauth settings ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION = True ACCOUNT_LOGOUT_ON_GET = True ACCOUNT_UNIQUE_EMAIL = True ACCOUNT_EMAIL_REQUIRED = True ACCOUNT_USERNAME_REQUIRED = False ACCOUNT_AUTHENTICATION_METHOD = 'email' ACCOUNT_EMAIL_VERIFICATION = 'mandatory' # Redirect URLs LOGIN_REDIRECT_URL = '/dashboard/' ACCOUNT_LOGOUT_REDIRECT_URL = '/'
URL Configuration
python# urls.py from django.urls import path, include urlpatterns = [ # ... path('accounts/', include('allauth.urls')), ]
Setting Up Google OAuth
- Go to Google Cloud Console
- Create a new project
- Enable Google+ API
- Create OAuth 2.0 credentials
- Set redirect URI:
http://localhost:8000/accounts/google/login/callback/
python# settings.py SOCIALACCOUNT_PROVIDERS = { 'google': { 'SCOPE': [ 'profile', 'email', ], 'AUTH_PARAMS': { 'access_type': 'online', }, 'OAUTH_PKCE_ENABLED': True, } }
Add credentials in Django admin:
- Go to
/admin/socialaccount/socialapp/ - Add a new Social Application
- Select Google as provider
- Enter Client ID and Secret Key
- Associate with your Site
Setting Up GitHub OAuth
- Go to GitHub Developer Settings
- Create a new OAuth App
- Set callback URL:
http://localhost:8000/accounts/github/login/callback/
python# settings.py SOCIALACCOUNT_PROVIDERS = { 'github': { 'SCOPE': [ 'user', 'read:user', 'user:email', ], }, }
Login Templates
html<!-- templates/account/login.html --> {% extends 'base.html' %} {% load socialaccount %} {% block content %} <h1>Login</h1> <!-- Standard login form --> <form method="post" action="{% url 'account_login' %}"> {% csrf_token %} {{ form.as_p }} <button type="submit">Login</button> </form> <hr> <h2>Or login with:</h2> <!-- Social login buttons --> {% get_providers as socialaccount_providers %} {% for provider in socialaccount_providers %} <a href="{% provider_login_url provider.id %}" class="btn btn-{{ provider.id }}"> Login with {{ provider.name }} </a> {% endfor %} <!-- Or direct links --> <a href="{% provider_login_url 'google' %}">Login with Google</a> <a href="{% provider_login_url 'github' %}">Login with GitHub</a> {% endblock %}
Handling Social Account Data
python# signals.py from allauth.account.signals import user_signed_up from allauth.socialaccount.signals import social_account_added from django.dispatch import receiver @receiver(user_signed_up) def handle_user_signed_up(request, user, **kwargs): """Handle new user registration.""" # Create profile, send welcome email, etc. Profile.objects.create(user=user) @receiver(social_account_added) def handle_social_account_added(request, sociallogin, **kwargs): """Handle when user connects a social account.""" user = sociallogin.user social_data = sociallogin.account.extra_data # Update profile with social data if sociallogin.account.provider == 'google': user.profile.avatar_url = social_data.get('picture') user.profile.save()
Custom Adapter
python# adapters.py from allauth.socialaccount.adapter import DefaultSocialAccountAdapter class CustomSocialAccountAdapter(DefaultSocialAccountAdapter): def pre_social_login(self, request, sociallogin): """Called before social login completes.""" # Connect social account to existing user with same email email = sociallogin.account.extra_data.get('email') if email: try: user = User.objects.get(email=email) sociallogin.connect(request, user) except User.DoesNotExist: pass def populate_user(self, request, sociallogin, data): """Populate user from social account data.""" user = super().populate_user(request, sociallogin, data) user.first_name = data.get('first_name', '') user.last_name = data.get('last_name', '') return user
python# settings.py SOCIALACCOUNT_ADAPTER = 'myapp.adapters.CustomSocialAccountAdapter'
Common Pitfalls
- Forgetting
AccountMiddleware: django-allauth requiresallauth.account.middleware.AccountMiddlewareinMIDDLEWARE. Without it, allauth views raise errors that are hard to debug. - Not handling email conflicts: When a user signs up with email first, then tries "Login with Google" using the same email, the accounts must be linked. Without
SOCIALACCOUNT_ADAPTERcustomization, users get a confusing error. - Skipping
ACCOUNT_EMAIL_VERIFICATION: Without email verification, an attacker can create an account with someone else's email, then use social login to take over the original account.
Best Practices
- Set
ACCOUNT_EMAIL_REQUIRED = TrueandACCOUNT_EMAIL_VERIFICATION = 'mandatory': This ensures email addresses are verified, preventing account takeover via email spoofing. - Store credentials in environment variables: Use
SOCIALACCOUNT_PROVIDERSwithAPP.client_idandAPP.secretreferencingos.environinstead of storing secrets in the database. - Write a custom
SocialAccountAdapter: Overridepre_social_login()to automatically link social accounts to existing users with the same verified email address.
Summary
- django-allauth provides social login for 80+ providers with minimal configuration.
- Install allauth, add it to
INSTALLED_APPS, configureAUTHENTICATION_BACKENDS, and include URLs. - Configure each provider's credentials via
SOCIALACCOUNT_PROVIDERSin settings. - Handle email conflicts with a custom
SocialAccountAdapter. - Always verify emails and store credentials in environment variables.
Code Examples
# settings.py
INSTALLED_APPS = [
...
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.google',
'allauth.socialaccount.providers.github',
]
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'allauth.account.auth_backends.AuthenticationBackend',
]