DEV Community

Cover image for How to Add Google OAuth to Django REST API
kihuni
kihuni

Posted on • Edited on

1

How to Add Google OAuth to Django REST API

User authentication is a crucial part of any modern web application, especially APIs that require secure access. Instead of traditional username-password logins, integrating Google OAuth allows users to authenticate seamlessly with their Google accounts. This enhances security, improves user experience, and eliminates the hassle of managing passwords.

In this guide, we’ll walk through how to add Google OAuth authentication to a Django REST API. By the end, users will be able to log in with Google, receive a JSON Web Token (JWT), and access protected API endpoints securely.

We'll cover:

✅ Setting up Google OAuth credentials in the Google Developer Console
✅ Configuring Django REST Framework with JWT authentication
✅ Implementing backend routes to handle Google login

Let’s dive in!

Why Google OAuth for a Django REST API?

For an API focused on project collaboration, Google OAuth with DRF offers:

  • Seamless Sign-In: Users log in with Google, skipping manual signup.
  • API Security: JWTs protect endpoints like /projects/ or /contributions/.
  • Developer Appeal: A trusted, scalable authentication method. This setup enhances user experience, making it quick and reliable for users to access your API.

Setting Up the Project

Let’s create a Django REST API from scratch, using Pipenv for environment management to keep dependencies clean.

Initial Setup
Create a Project Directory:

mkdir ProjectAPI
cd ProjectAPI
Enter fullscreen mode Exit fullscreen mode

Install Dependencies:
Add Django, DRF, and OAuth tools:

pipenv install django djangorestframework django-allauth djangorestframework-simplejwt python-decouple
Enter fullscreen mode Exit fullscreen mode

Activate the Virtual Environment

pipenv shell
Enter fullscreen mode Exit fullscreen mode

Start the Django Project:

pipenv run django-admin startproject ProjectAPI .
Enter fullscreen mode Exit fullscreen mode

Note: The . keeps the project files in the current directory.

Add an App:

pipenv run python manage.py startapp core
Enter fullscreen mode Exit fullscreen mode

Test the Setup:

pipenv run python manage.py runserver
Enter fullscreen mode Exit fullscreen mode

Visit http://localhost:8000/ to confirm it’s working.

testing

Task 1: Set Up Google OAuth Credentials

Google OAuth starts with registering your app in the Developer Console.

Steps:
Step 1. Create a Project:

google cloud console

  • Create a project (e.g., "ProjectCollabAPI").

  • Choose the Organization and Location (if applicable).

  • Click Create.

Creating project

Step 2. Enable APIs:

  • In the Google Cloud Console, select the project you just created.
  • Navigate to APIs & Services > Library.
  • Search for "Google+ API" or "People API" .

Enable OAuth

and click "Enable." This allows your app to access user info.

enabled

Step 3. Configure OAuth Consent Screen:

Still on the "APIs & Services", go to the "OAuth consent screen."

You will see a "Google Auth Platform not configured yet" message with a "Get started" button—this is normal for a new project. Click "Get started."

Choose User Type:

Select "External" to allow any Google account to sign in (good for testing). Click "Create."

Image description

Add app Information:

  • App Name: Enter "Project Collaboration API."
  • User Support Email: Use your Gmail address.
  • App Logo (optional): Upload a 512x512px image (e.g., a handshake icon).

  • App Domain (optional): Skip for now unless you have a production domain.

  • Developer Contact Information: Add your email.

  • Click "Save and Continue."

app info

Scopes:
Click "Add or Remove Scopes."

Add profile and email (e.g., https://www.googleapis.com/auth/userinfo.profile, https://www.googleapis.com/auth/userinfo.email) to access basic user info.

scopes

Click "Update," then "Save and Continue."

scopes

Test Users (optional):
If prompted, add your Gmail as a test user for development.

Click "Save and Continue."

Step 4. Create Credentials:

In the left sidebar, go to "APIs & Services" > "Credentials."

  • Click "Create Credentials" > "OAuth 2.0 Client IDs."

create credentials

  • Select "Web application."
  • Set "Authorized redirect URIs" to:

- http://localhost:8000/auth/google/login/callback/ (for the default Django development server port using localhost).
- http://127.0.0.1:8000/auth/google/login/callback/ (if you access via 127.0.0.1).
- Add additional URIs if you use a different port (e.g., http://localhost:8080/auth/google/login/callback/, http://127.0.0.1:8080/auth/google/login/callback/).

Note: The callback path /auth/google/login/callback/ is the default path used by django-allauth for the Google provider when the base path is /auth/. This path is determined by django-allauth’s URL patterns for the Google provider.

  • Click "Create" and note your Client ID and Client Secret.

create

Secure Storage

In .env (create this file in ProjectAPI/):

GOOGLE_CLIENT_ID=your-client-id-here
GOOGLE_CLIENT_SECRET=your-client-secret-here
Enter fullscreen mode Exit fullscreen mode

In ProjectAPI/settings.py:
python

from decouple import config
GOOGLE_CLIENT_ID = config('GOOGLE_CLIENT_ID')
GOOGLE_CLIENT_SECRET = config('GOOGLE_CLIENT_SECRET')
Enter fullscreen mode Exit fullscreen mode

Task 2: Configure JWT for Authenticated Users

For an API app, JWTs provide stateless authentication, ideal for securing endpoints after Google sign-in. Let’s configure the necessary settings in ProjectAPI/settings.py.

Update settings.py

Add the following to enable Django’s authentication, DRF, allauth for Google OAuth, and SimpleJWT for token-based API access:


INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.sites',
    'rest_framework',
    'rest_framework_simplejwt',
    'allauth',
    'allauth.account',
    'allauth.socialaccount',
    'allauth.socialaccount.providers.google',
    'core',
]

SITE_ID = 1
AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'allauth.account.auth_backends.AuthenticationBackend',
]
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ),
}

SOCIALACCOUNT_PROVIDERS = {
    'google': {
        'SCOPE': ['profile', 'email'],
        'AUTH_PARAMS': {'access_type': 'online'},
    }
}

MIDDLEWARE = [
 ...
    'allauth.account.middleware.AccountMiddleware',  # Required for allauth
]
...
Enter fullscreen mode Exit fullscreen mode

Understanding the Settings
Let’s break down what each part does:

INSTALLED_APPS:

  • 'django.contrib.auth': Enables Django’s user authentication system (e.g., User model, login/logout).
  • 'django.contrib.contenttypes': Supports generic relationships, used by other apps.
  • 'django.contrib.sessions': Manages user sessions during the OAuth flow (even though we’ll use JWTs for API access).
  • 'django.contrib.messages': Handles one-time messages (e.g., success notifications).
  • 'django.contrib.staticfiles': Manages static files for the minimal frontend.
  • 'django.contrib.sites': Required by allauth to associate users with a site.
  • 'rest_framework': Adds DRF for API functionality.
  • 'rest_framework_simplejwt': Provides JWT authentication for DRF.
  • 'allauth', 'allauth.account', 'allauth.socialaccount': Core allauth packages for authentication and social logins.
  • 'allauth.socialaccount.providers.google': Enables Google OAuth support.
  • 'core': Your custom app for API logic.

SITE_ID = 1:

  • Identifies the site your app runs on, required by allauth—the default SITE_ID of 1 matches the first site in the django_site table (created during migration).

AUTHENTICATION_BACKENDS:

  • 'django.contrib.auth.backends.ModelBackend': Default Django backend for username/password authentication.
  • 'allauth.account.auth_backends.AuthenticationBackend': Handles allauth’s authentication, including Google OAuth.

REST_FRAMEWORK:

  • 'DEFAULT_AUTHENTICATION_CLASSES': Sets JWT as the default authentication method for DRF. After Google sign-in, users get a JWT to access API endpoints.

SOCIALACCOUNT_PROVIDERS:

  • Configures Google OAuth settings for allauth.

  • 'SCOPE': ['profile', 'email']: Requests the user’s name and email.

  • 'AUTH_PARAMS': {'access_type': 'online'}: Ensures the OAuth flow is for online access (no refresh tokens needed).

  • MIDDLEWARE:

  • 'allauth.account.middleware.AccountMiddleware': Required by django-allauth (version 0.53.0+) to manage user authentication flows, such as Google OAuth. It must come after AuthenticationMiddleware.

Migrate

Run migrations to apply these changes:

pipenv run python manage.py migrate
Enter fullscreen mode Exit fullscreen mode

migrations

Troubleshooting

Error: allauth.account.middleware.AccountMiddleware missing:

  • If you see ImproperlyConfigured: allauth.account.middleware.AccountMiddleware must be added to settings.MIDDLEWARE, ensure you’re using django-allauth version 0.53.0 or higher (check with pipenv run pip show django-allauth). Add the middleware as shown above, after AuthenticationMiddleware.

Error: ModuleNotFoundError: No module named 'requests':

  • The requests library is required by allauth.socialaccount.providers.google to make HTTP requests to Google’s OAuth endpoints. Install it with:
pipenv install requests
Enter fullscreen mode Exit fullscreen mode

Error: ModuleNotFoundError: No module named 'cryptography':

  • The cryptography library is required by allauth for secure JWT handling in Google OAuth. Install it with:
pipenv install cryptography
Enter fullscreen mode Exit fullscreen mode

Configure the Google SocialApp in the Database

Before you can use Google OAuth, you need to configure a SocialApp in the database to store your Google OAuth credentials. django-allauth uses this to authenticate with Google.

Step 1. Create a Superuser:

To access the Django admin interface, create a superuser account:

pipenv run python manage.py createsuperuser
Enter fullscreen mode Exit fullscreen mode

Follow the prompts to set a username, email, and password.

Step 2. Access the Admin Interface:
Start the server:

pipenv run python manage.py runserver
Enter fullscreen mode Exit fullscreen mode

Visit http://localhost:8000/admin/ and log in with your superuser credentials.

Admin dashboard

Step 3. Add a Google SocialApp:

In the admin interface, under Social Accounts, click Social applications > Add social application.

Fill in the form:

  • Provider: Select "Google".
  • Name: Enter "Google OAuth".
  • Client ID: Enter the GOOGLE_CLIENT_ID from your .env file.
  • Secret key: Enter the GOOGLE_CLIENT_SECRET from your .env file.
  • Key: Leave blank.
  • Sites: Move the site with SITE_ID=1 (e.g., example.com) to the "Chosen sites" box.
  • Click Save.

This step ensures django-allauth can find the Google credentials when initiating the OAuth flow.

admin

Task 3: Implement Backend Routes

We’ll set up routes for Google login, token issuance, and a sample /projects/ endpoint.

URLs

In ProjectAPI/urls.py:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('auth/', include('allauth.urls')),
    path('api/', include('core.urls')),
]
Enter fullscreen mode Exit fullscreen mode

In core/urls.py:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.home, name='home'),
    path('token/', views.get_jwt_token, name='get_token'),
    path('projects/', views.projects, name='projects'),
]
Enter fullscreen mode Exit fullscreen mode

Views
In core/views.py:

from django.shortcuts import render
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework_simplejwt.tokens import RefreshToken

def home(request):
    return render(request, 'core/home.html')

@api_view(['GET'])
def get_jwt_token(request):
    if not request.user.is_authenticated:
        return Response({"error": "Please sign in first"}, status=401)
    refresh = RefreshToken.for_user(request.user)
    return Response({
        'refresh': str(refresh),
        'access': str(refresh.access_token),
    })

@api_view(['GET'])
@permission_classes([IsAuthenticated])
def projects(request):
    data = {
        "message": "Welcome to the project collaboration API!",
        "user": request.user.email,
        "projects": ["Sample Project 1", "Sample Project 2"]
    }
    return Response(data)
Enter fullscreen mode Exit fullscreen mode

Custom Adapter

In core/adapters.py. Add:

from allauth.socialaccount.adapter import DefaultSocialAccountAdapter

class CustomSocialAccountAdapter(DefaultSocialAccountAdapter):
    def save_user(self, request, sociallogin, form=None):
        user = super().save_user(request, sociallogin, form)
        sociallogin.state['next'] = '/api/token/'
        return user

Enter fullscreen mode Exit fullscreen mode

In settings.py. Add:

SOCIALACCOUNT_ADAPTER = 'core.adapters.CustomSocialAccountAdapter'
Enter fullscreen mode Exit fullscreen mode

The custom adapter controls what happens after a user logs in with Google. Here’s what it does:

Why It’s Needed:

  • By default, after a Google login, django-allauth redirects the user to a default URL (e.g., /accounts/profile/) or a URL specified in the next parameter of the login request.

  • In an API app, you want the user to be redirected to /api/token/ to immediately obtain a JWT for API access, rather than a generic page.

How It Works:

  • CustomSocialAccountAdapter: This class inherits from DefaultSocialAccountAdapter, the default adapter for social logins in allauth.

save_user Method:

  • Called by allauth when a user logs in with Google to create or link a Django User.
  • super().save_user(request, sociallogin, form): Calls the default save_user method to handle user creation/linking.
  • sociallogin.state['next'] = '/api/token/': Sets the redirect URL to /api/token/ after login. The sociallogin.state dictionary is used by allauth to manage redirect state.

SOCIALACCOUNT_ADAPTER Setting:

  • Tells allauth to use your custom adapter (core.adapters.CustomSocialAccountAdapter) instead of the default one.

Role in the Flow:

  • After the user logs in with Google and is redirected back to /auth/google/callback/, allauth uses the custom adapter to set the redirect to /api/token/.
  • At /api/token/, the get_jwt_token view issues a JWT, which the user can use to access protected endpoints like /api/projects/.

Troubleshooting

Error: SocialApp.DoesNotExist:

If you see this error when trying to log in with Google, it means the Google SocialApp is not configured in the database. Ensure you’ve completed adding a Google SocialApp via the Django admin interface, including your GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET.

Frontend

Create templates/core/:

home.html:


<!DOCTYPE html>
<html>
<head><title>Project Collaboration API</title></head>
<body>
  <h1>Sign In with Google</h1>
  {% if user.is_authenticated %}
    <p>Welcome, {{ user.first_name }}! <a href="/api/token/">Get JWT Token</a></p>
    <p><a href="/auth/logout/">Logout</a></p>
  {% else %}
    <p><a href="/auth/google/login/?process=login">Sign In with Google</a></p>
  {% endif %}
</body>
</html>

Enter fullscreen mode Exit fullscreen mode

In settings.py:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates'],
        'APP_DIRS': True,
        ...
    },
]
Enter fullscreen mode Exit fullscreen mode

The Flow

  • Sign-In: /auth/google/login/ → Google → /auth/google/login/callback/.
  • Token: Redirects to/api/token/ for a JWT (thanks to the custom adapter).
  • API: Use the access token in Authorization: Bearer <token> for /api/projects/.

Testing the Authentication

Activate Pipenv:

pipenv shell
Enter fullscreen mode Exit fullscreen mode

Run the server:

python manage.py runserver
Enter fullscreen mode Exit fullscreen mode

Visit http://localhost:8000/api/, and sign in.

browsable api

sign in

sign in

Get your JWT, and test /api/projects/:

curl -H "Authorization: Bearer <access_token>" http://localhost:8000/api/projects/
Enter fullscreen mode Exit fullscreen mode

token

Conclusion

You’ve now added Google OAuth to a Django REST API, creating a seamless sign-in option that boosts user experience.

Summary

  • We Set up Google OAuth credentials.
  • Configured JWT for authenticated users.
  • Configured the Google SocialApp in the database.
  • Implemented backend routes for login and API access.
  • This foundation is ready for project collaboration features—expand it with your endpoints! Check out Django-Allauth Docs or DRF Docs for more.

What I Offer

Need a custom API solution? Here’s what I bring:

  • Custom Django REST APIs: Secure, scalable backends tailored to your needs.
  • Fast API Development: Using DRF and GraphQL for rapid builds.
  • Authentication & Security: JWT, OAuth2, rate limiting, CORS, API keys.
  • Database Optimization: Tuning PostgreSQL, MySQL, Redis, or MongoDB.
  • Third-Party API Integrations: Stripe, Twilio, OpenAI, Zapier, Google Maps, and more.
  • Real-time Features: WebSockets and Celery for dynamic apps.
  • Comprehensive API Documentation: Swagger, OpenAPI, or Postman for clarity.
  • Let’s build something amazing together!

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

Playwright CLI Flags Tutorial

5 Playwright CLI Flags That Will Transform Your Testing Workflow

  • 0:56 --last-failed: Zero in on just the tests that failed in your previous run
  • 2:34 --only-changed: Test only the spec files you've modified in git
  • 4:27 --repeat-each: Run tests multiple times to catch flaky behavior before it reaches production
  • 5:15 --forbid-only: Prevent accidental test.only commits from breaking your CI pipeline
  • 5:51 --ui --headed --workers 1: Debug visually with browser windows and sequential test execution

Learn how these powerful command-line options can save you time, strengthen your test suite, and streamline your Playwright testing experience. Click on any timestamp above to jump directly to that section in the tutorial!

Watch Full Video 📹️

👋 Kindness is contagious

If you found this article helpful, please give a ❤️ or share a friendly comment!

Got it