Post

Google Authentication in Django: Implementation Guide

Learn to integrate Google OAuth2 authentication into your Django app with social-auth-app-django, covering setup, configuration, and security best practices.

Google Authentication in Django: Implementation Guide

1. Set up Google OAuth Credentials

First, create OAuth credentials in the Google Cloud Console as described earlier:

  • Go to Google Cloud Console
  • Create/select a project
  • Create OAuth 2.0 client ID credentials
  • Note your Client ID and Client Secret

2. Install Required Package

You’ll need the requests library to make HTTP requests to Google’s API:

1
pip install requests

3. Create Authentication Views

Create a new app for authentication or use an existing one:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# auth_app/views.py
import os
import json
import requests
from django.shortcuts import redirect
from django.contrib.auth import login
from django.contrib.auth.models import User
from django.conf import settings
from django.urls import reverse
from django.http import JsonResponse

# Your Google OAuth settings
GOOGLE_CLIENT_ID = 'YOUR_CLIENT_ID'
GOOGLE_CLIENT_SECRET = 'YOUR_CLIENT_SECRET'
REDIRECT_URI = 'http://yourdomain.com/auth/google/callback/'  # Adjust to your domain

def google_login(request):
    """Initiates the OAuth 2.0 flow by redirecting to Google"""
    # Generate the Google authorization URL
    auth_url = "https://accounts.google.com/o/oauth2/auth"
    params = {
        'client_id': GOOGLE_CLIENT_ID,
        'redirect_uri': request.build_absolute_uri(reverse('google_callback')),
        'response_type': 'code',
        'scope': 'email profile',
        'access_type': 'online',
    }
    
    # Build the authorization URL with parameters
    auth_url = f"{auth_url}?{'&'.join([f'{key}={value}' for key, value in params.items()])}"
    
    # Redirect the user to Google's authorization page
    return redirect(auth_url)

def google_callback(request):
    """Handles the callback from Google after user authorizes"""
    code = request.GET.get('code')
    
    if not code:
        return JsonResponse({'error': 'Authentication failed'}, status=400)
    
    # Exchange the authorization code for an access token
    token_url = "https://oauth2.googleapis.com/token"
    token_data = {
        'code': code,
        'client_id': GOOGLE_CLIENT_ID,
        'client_secret': GOOGLE_CLIENT_SECRET,
        'redirect_uri': request.build_absolute_uri(reverse('google_callback')),
        'grant_type': 'authorization_code',
    }
    
    # Get the access token
    token_response = requests.post(token_url, data=token_data)
    token_json = token_response.json()
    
    if 'access_token' not in token_json:
        return JsonResponse({'error': 'Failed to obtain access token'}, status=400)
    
    # Use the access token to get user info
    user_info_url = "https://www.googleapis.com/oauth2/v2/userinfo"
    headers = {'Authorization': f"Bearer {token_json['access_token']}"}
    user_info_response = requests.get(user_info_url, headers=headers)
    user_info = user_info_response.json()
    
    # Check if user exists or create a new one
    try:
        user = User.objects.get(email=user_info['email'])
    except User.DoesNotExist:
        # Create a new user
        user = User.objects.create_user(
            username=user_info['email'],
            email=user_info['email'],
            first_name=user_info.get('given_name', ''),
            last_name=user_info.get('family_name', '')
        )
        
        # Create a user profile if needed
        # UserProfile.objects.create(user=user, google_id=user_info['id'])
    
    # Log the user in
    login(request, user)
    
    # Redirect to home page or dashboard
    return redirect('home')  # Change to your home URL name

4. Add URL Patterns

Add these to your urls.py:

1
2
3
4
5
6
7
8
# auth_app/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('auth/google/login/', views.google_login, name='google_login'),
    path('auth/google/callback/', views.google_callback, name='google_callback'),
]

And include these URLs in your project’s main urls.py:

1
2
3
4
5
6
7
# project/urls.py
from django.urls import path, include

urlpatterns = [
    # ... other URL patterns
    path('', include('auth_app.urls')),
]

5. Create a Simple Login Template

1
2
3
4
5
6
7
8
9
10
11
<!-- templates/login.html -->
<!DOCTYPE html>
<html>
<head>
    <title>Login</title>
</head>
<body>
    <h2>Login</h2>
    <a href="{% url 'google_login' %}">Login with Google</a>
</body>
</html>

6. Add View for the Login Page

1
2
3
4
5
# auth_app/views.py (additional function)
from django.shortcuts import render

def login_page(request):
    return render(request, 'login.html')

And add it to your URLs:

1
2
# auth_app/urls.py (additional URL)
path('login/', views.login_page, name='login_page'),

7. Add Settings

Add these to your settings.py:

1
2
3
4
5
6
7
8
9
# Required for authentication
AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    # Add a custom authentication backend if needed
]

# Redirect URLs
LOGIN_REDIRECT_URL = '/'  # Where to redirect after login
LOGOUT_REDIRECT_URL = '/'  # Where to redirect after logout

8. User Profile Model (Optional)

If you want to store additional information about the user:

1
2
3
4
5
6
7
8
9
10
11
# auth_app/models.py
from django.db import models
from django.contrib.auth.models import User

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    google_id = models.CharField(max_length=100, unique=True)
    profile_picture = models.URLField(blank=True, null=True)
    
    def __str__(self):
        return self.user.username

Remember to run migrations if you create a new model:

1
2
python manage.py makemigrations
python manage.py migrate

This baremetal approach gives you more control over the authentication flow but requires more maintenance compared to using established packages like django-allauth. You’ll need to handle token refreshing, session management, and error handling yourself.

Would you like me to explain any specific part of this implementation in more detail?

This post is licensed under CC BY 4.0 by the author.