Django Googler is a simple way to integrate Google Auth Platform with your Django project.
Project description
Django Googler
Django Googler is a simple way to integrate Google OAuth Platform with your Django project. It provides both Django Rest Framework API views and regular Django views for handling Google OAuth authentication flows.
Features
- 🔐 Google OAuth 2.0 Integration - Complete OAuth flow implementation
- 🎯 Dual View Support - Both DRF API views and regular Django views
- 🔧 Service Layer Architecture - Clean separation of business logic
- ⚙️ Highly Configurable - Override settings via Django settings
- 🛡️ CSRF Protection - Built-in state verification
- 👥 Automatic User Management - Create or update users from Google info
- 📦 Zero Configuration - Works out of the box with sensible defaults
- 🚦 Rate Limiting - Built-in throttling to prevent abuse
- ✅ Settings Validation - Django system checks for configuration
- 📝 DRF Serializers - Proper request/response validation
Installation
pip install django-googler
Dependencies
Quick Start
1. Add to Installed Apps
# settings.py
INSTALLED_APPS = [
# ...
"rest_framework",
"rest_framework.authtoken", # Required for API token authentication
"django_googler",
]
2. Configure Google OAuth Settings
Get your credentials from Google Cloud Console:
# settings.py
import os
# Required: Get these from Google Cloud Console
GOOGLE_OAUTH_CLIENT_ID = os.environ.get("GOOGLE_OAUTH_CLIENT_ID")
GOOGLE_OAUTH_CLIENT_SECRET = os.environ.get("GOOGLE_OAUTH_CLIENT_SECRET")
# Optional: Override default redirect URIs
GOOGLE_OAUTH_REDIRECT_URIS = [
"http://localhost:8000/auth/google/callback/",
"http://localhost:8000/api/auth/google/callback/",
]
# Optional: Override default scopes
GOOGLE_OAUTH_SCOPES = [
"openid",
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile",
]
# Optional: Store OAuth tokens in session (useful for making Google API calls from backend)
# Default: False
GOOGLE_OAUTH_STORE_TOKENS = True
# Optional: Return Google tokens in API callback response (for frontend Google API calls)
# Default: False (only returns DRF token)
GOOGLE_OAUTH_RETURN_TOKENS = False
# Optional: Login URL for error redirects
# Default: "/login/"
LOGIN_URL = "/admin/login/"
3. Run Migrations
python manage.py migrate
This creates the necessary database tables for the authtoken app.
4. Add URL Patterns
Choose between Regular Django Views or Django Rest Framework API Views (or use both!):
Regular Django Views
# urls.py
from django.urls import path, include
urlpatterns = [
path("auth/", include("django_googler.urls.default")),
]
Or explicitly:
# urls.py
from django.urls import path
from django_googler import GoogleOAuthLoginView, GoogleOAuthCallbackView
urlpatterns = [
path("auth/google/login/", GoogleOAuthLoginView.as_view(), name="google-login"),
path(
"auth/google/callback/",
GoogleOAuthCallbackView.as_view(),
name="google-callback",
),
]
Django Rest Framework API Views
# urls.py
from django.urls import path, include
urlpatterns = [
path("api/auth/", include("django_googler.urls.drf")),
]
Or explicitly:
# urls.py
from django.urls import path
from django_googler import (
GoogleOAuthLoginAPIView,
GoogleOAuthCallbackAPIView,
CurrentUserAPIView,
GoogleOAuthLogoutAPIView,
)
urlpatterns = [
path(
"api/auth/google/login/",
GoogleOAuthLoginAPIView.as_view(),
name="google-login-api",
),
path(
"api/auth/google/callback/",
GoogleOAuthCallbackAPIView.as_view(),
name="google-callback-api",
),
path("api/auth/me/", CurrentUserAPIView.as_view(), name="current-user"),
path("api/auth/logout/", GoogleOAuthLogoutAPIView.as_view(), name="logout"),
]
Usage
Regular Django Views (Browser Redirects)
-
Redirect users to the login view:
<a href="{% url 'django_googler:google-login' %}?next=/dashboard/">Sign in with Google</a>
-
Users are redirected to Google for authentication
-
After authentication, users are redirected back and automatically logged in
The regular Django views will:
- Create a new user if they don't exist
- Update existing user information
- Log the user into Django's authentication system
- Redirect to the
nextparameter or/by default
Django Rest Framework API Views (JSON Responses)
-
GET the login endpoint to get the authorization URL:
curl http://localhost:8000/api/auth/google/login/Response:
{ "authorization_url": "https://accounts.google.com/o/oauth2/auth?...", "state": "random-state-string" }
-
Redirect users to the
authorization_url -
After Google redirects back with the authorization code, POST it to the callback:
curl -X POST http://localhost:8000/api/auth/google/callback/ \ -H "Content-Type: application/json" \ -d '{ "code": "4/0AY0e-g...", "state": "random-state-string", "redirect_uri": "http://localhost:3000/auth/callback" }'
Response (user is created/logged in and API token returned):
{ "token": "drf_api_token_abc123...", "user": { "id": 1, "email": "user@example.com", "username": "user", "first_name": "John", "last_name": "Doe" } }
Note: Google tokens are not included by default. If your frontend needs to call Google APIs directly (Calendar, Drive, Gmail, etc.), set
GOOGLE_OAUTH_RETURN_TOKENS = Truein settings to include them in the response. -
Use the returned token for authenticated requests:
curl http://localhost:8000/api/protected/ \ -H "Authorization: Token drf_api_token_abc123..."
Additional DRF Endpoints
Get Current User
curl http://localhost:8000/api/auth/me/ \
-H "Authorization: Token your-token-here"
Response:
{
"id": 1,
"email": "user@example.com",
"username": "user",
"first_name": "John",
"last_name": "Doe"
}
Logout
curl -X POST http://localhost:8000/api/auth/logout/ \
-H "Authorization: Token your-token-here"
Response:
{
"message": "Logged out successfully"
}
This will:
- Delete the user's DRF authentication token
- Clear all OAuth session data (access tokens, refresh tokens, etc.)
Advanced Usage
Using the Service Layer
You can use the service layer directly in your own views or logic:
from django_googler import GoogleOAuthService, UserService, OAuthFlowService
# Verify and process OAuth credentials
credentials_data = GoogleOAuthService.process_credentials(credentials)
# Create or update user from OAuth info
user = UserService.get_or_create_user(
email="user@example.com",
name="John Doe",
google_id="1234567890",
picture="https://...",
)
# Manage OAuth flow state
OAuthFlowService.store_state(request, state)
is_valid = OAuthFlowService.verify_state(request, state)
OAuthFlowService.clear_state(request)
Custom Scopes
Request additional Google API scopes:
<!-- In your template -->
<a href="{% url 'django_googler:google-login' %}?scopes=openid,email,profile,https://www.googleapis.com/auth/calendar">
Sign in with Google Calendar Access
</a>
Or for API views:
curl "http://localhost:8000/api/auth/google/login/?scopes=openid,email,profile"
Storing OAuth Tokens
If you want to make API calls to Google on behalf of users, enable token storage:
# settings.py
GOOGLE_OAUTH_STORE_TOKENS = True
Then access tokens in your views:
def my_view(request):
access_token = request.session.get("google_access_token")
refresh_token = request.session.get("google_refresh_token")
token_expiry = request.session.get("google_token_expiry")
# Use tokens to make Google API calls
# ...
Extending User Creation
If you need to store additional user information (like google_id or picture), you can:
-
Create a custom user model:
from django.contrib.auth.models import AbstractUser class User(AbstractUser): google_id = models.CharField(max_length=255, blank=True) picture = models.URLField(blank=True)
-
Or create a user profile model:
class UserProfile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) google_id = models.CharField(max_length=255, blank=True) picture = models.URLField(blank=True)
-
Override the UserService (recommended):
from django_googler.services import UserService as BaseUserService class CustomUserService(BaseUserService): @staticmethod def _create_new_user( email, name=None, given_name=None, family_name=None, google_id=None, picture=None, ): user = super()._create_new_user( email, name, given_name, family_name, google_id, picture ) # Store additional fields if google_id: user.google_id = google_id if picture: user.picture = picture user.save() return user
Architecture
Django Googler follows a clean service-layer architecture:
views.py- View layer (DRF and Django views)services.py- Business logic layerGoogleOAuthService- OAuth token processingUserService- User creation and managementOAuthFlowService- OAuth state management
platform_client.py- Google OAuth client wrapperdefaults.py- Configuration and settings
Configuration Reference
All settings are optional and have sensible defaults:
| Setting | Default | Description |
|---|---|---|
GOOGLE_OAUTH_CLIENT_ID |
"" |
Google OAuth Client ID (required) |
GOOGLE_OAUTH_CLIENT_SECRET |
"" |
Google OAuth Client Secret (required) |
GOOGLE_OAUTH_REDIRECT_URIS |
["http://localhost:8000/api/googler/callback"] |
Authorized redirect URIs |
GOOGLE_OAUTH_SCOPES |
["openid", "email", "profile"] |
OAuth scopes to request |
GOOGLE_OAUTH_STORE_TOKENS |
False |
Store tokens in session |
GOOGLE_OAUTH_RETURN_TOKENS |
False |
Return Google tokens in API response |
LOGIN_URL |
"/login/" |
Redirect URL on OAuth errors |
Rate Limiting
Django Googler includes built-in rate limiting for OAuth endpoints:
- Login endpoint: 10 requests per hour
- Callback endpoint: 20 requests per hour
You can customize these rates in your Django REST Framework settings:
# settings.py
REST_FRAMEWORK = {
"DEFAULT_THROTTLE_RATES": {
"anon": "100/hour",
"user": "1000/hour",
}
}
Error Handling
The views handle various error scenarios:
| Error Code | Description |
|---|---|
oauth_init_failed |
Failed to initiate OAuth flow |
missing_code |
Authorization code not provided by Google |
invalid_state |
CSRF state verification failed |
no_email |
Google didn't provide an email address |
oauth_callback_failed |
General callback processing error |
Access errors via query parameters:
def login_view(request):
error = request.GET.get("error")
if error == "invalid_state":
messages.error(request, "Security check failed. Please try again.")
Google Cloud Console Setup
- Go to Google Cloud Console
- Create a new project or select existing one
- Enable the Google+ API and People API
- Go to Credentials → Create Credentials → OAuth 2.0 Client ID
- Configure Authorized redirect URIs:
- For local development:
http://localhost:8000/auth/google/callback/ - For production:
https://yourdomain.com/auth/google/callback/
- For local development:
- Copy the Client ID and Client Secret to your Django settings
License
MIT License - see LICENSE file for details
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Support
For issues and questions, please use the GitHub issue tracker.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_googler-0.0.3.tar.gz.
File metadata
- Download URL: django_googler-0.0.3.tar.gz
- Upload date:
- Size: 46.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7f879b764592272c43629c2a0c97b0387631412d2cc04dab46a2c03c407e6895
|
|
| MD5 |
8aace276b91c784d91bd4640bb1c3966
|
|
| BLAKE2b-256 |
450433a6f411dacfb12bfd9f3ae3438ba8f4af35336fdd6ef3130c41cb307338
|
Provenance
The following attestation bundles were made for django_googler-0.0.3.tar.gz:
Publisher:
main.yaml on jmitchel3/django-googler
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_googler-0.0.3.tar.gz -
Subject digest:
7f879b764592272c43629c2a0c97b0387631412d2cc04dab46a2c03c407e6895 - Sigstore transparency entry: 621052597
- Sigstore integration time:
-
Permalink:
jmitchel3/django-googler@41b067f3f4057d31026d907ca118432eafab3465 -
Branch / Tag:
refs/tags/v0.0.3 - Owner: https://github.com/jmitchel3
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
main.yaml@41b067f3f4057d31026d907ca118432eafab3465 -
Trigger Event:
push
-
Statement type:
File details
Details for the file django_googler-0.0.3-py3-none-any.whl.
File metadata
- Download URL: django_googler-0.0.3-py3-none-any.whl
- Upload date:
- Size: 17.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b0bb010b60490670c2efb2ec6967f74586d3e34efab83d07f945fc1cddeb32e2
|
|
| MD5 |
231a4d9d67cd22b38f09d65374c2c970
|
|
| BLAKE2b-256 |
7f21233e39a203e8b8e128fbb9a3e4bce229763db1ea392fce903b9bca8cc2d6
|
Provenance
The following attestation bundles were made for django_googler-0.0.3-py3-none-any.whl:
Publisher:
main.yaml on jmitchel3/django-googler
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_googler-0.0.3-py3-none-any.whl -
Subject digest:
b0bb010b60490670c2efb2ec6967f74586d3e34efab83d07f945fc1cddeb32e2 - Sigstore transparency entry: 621052599
- Sigstore integration time:
-
Permalink:
jmitchel3/django-googler@41b067f3f4057d31026d907ca118432eafab3465 -
Branch / Tag:
refs/tags/v0.0.3 - Owner: https://github.com/jmitchel3
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
main.yaml@41b067f3f4057d31026d907ca118432eafab3465 -
Trigger Event:
push
-
Statement type: