Django Social Auth REST - Social Login for Django APIs
Add Google and GitHub login to your Django REST API in minutes. Handles token verification, account linking/unlinking, and JWT tokens out of the box.
django-social-auth-rest adds social login to Django and Django REST Framework projects. It verifies tokens with Google or GitHub, creates or links user accounts, and hands back JWT tokens your frontend can use immediately - plus the ability to link, unlink, and list connected providers after the fact. Drop it in and skip the part where you write the same OAuth glue code for the fifth time.
More providers coming soon. Want one added? Open an issue or submit a pull request.
The problem it solves
Social login sounds simple until you actually build it. You end up writing the same handful of things every time:
- Verifying that a Google or GitHub token is actually legitimate
- Fetching the user’s profile from the provider
- Creating a new account if the user is new
- Linking to an existing account when the email already matches
- Letting users connect or disconnect providers later
- Issuing a token the frontend can use for future requests
- Rate-limiting the login endpoint so it can’t be abused
django-social-auth-rest handles all of it, so you can wire up a button and move on.
What it does
Sign in with Google or GitHub. Users log in with an existing account on either provider. Tokens are verified directly with the provider first - invalid or expired tokens are rejected before anything else happens.
Creates accounts automatically. A first-time social login creates a Django user from the verified provider details. Nothing extra to wire up.
Links to existing accounts. If the verified email already belongs to a user, the social login is attached to that account instead of creating a duplicate.
Link and unlink accounts after the fact. Authenticated users can connect additional providers to their existing account or remove ones they’ve already connected - and check which providers are currently linked.
Returns JWT tokens immediately. A successful login returns an access token and a refresh token, ready for the frontend to use right away.
Works with any frontend. Standard REST endpoints - fine with React, Next.js, Vue, Flutter, or any mobile client that can make an HTTP request.
Works with your existing user model. Drops into projects with a custom user model without changes to your setup.
Protects against abuse. Every auth endpoint is rate-limited by default.
Supports soft-deleted accounts. If your user model marks accounts as deleted rather than removing them, you can block those accounts from logging in or linking through social auth.
Sends signals for your own logic. Registration, login, linking, and unlinking each fire a Django signal, so you can hook in welcome emails, analytics, or anything else.
How login works
Google uses an ID token flow:
- The frontend handles Google sign-in and gets back an ID token
- That token is sent to your Django API
- The backend verifies it with Google
- The backend finds or creates the user and returns JWT tokens
GitHub uses the OAuth 2.0 authorization code flow, with a signed state token for CSRF protection:
- The frontend requests a state token from your API
- The frontend redirects the user to GitHub with that state token
- GitHub redirects back with an authorization code
- The frontend sends the code and state to your API
- The backend validates the state, exchanges the code with GitHub, and returns JWT tokens
API endpoints
| Method | Endpoint | What it does |
|---|---|---|
| POST | /api/social-auth/google/login/ | Log in or sign up with a Google ID token |
| POST | /api/social-auth/google/link/ | Link Google to the authenticated user (auth required) |
| POST | /api/social-auth/google/unlink/ | Remove the Google link (auth required) |
GitHub
| Method | Endpoint | What it does |
|---|---|---|
| GET | /api/social-auth/github/state/ | Get a signed state token before starting the flow |
| POST | /api/social-auth/github/login/ | Log in or sign up with a GitHub code |
| POST | /api/social-auth/github/link/ | Link GitHub to the authenticated user (auth required) |
| POST | /api/social-auth/github/unlink/ | Remove the GitHub link (auth required) |
Account status
| Method | Endpoint | What it does |
|---|---|---|
| GET | /api/social-auth/linked-accounts/ | List enabled providers and whether the current user has linked each one (auth required) |
Setup
1. Install the package
pip install django-social-auth-rest
2. Add it to INSTALLED_APPS
# settings.py
INSTALLED_APPS = [
"rest_framework",
"django_social_auth_rest",
]
3. Set up JWT authentication
# settings.py
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework_simplejwt.authentication.JWTAuthentication",
),
}
from datetime import timedelta
SIMPLE_JWT = {
"AUTH_HEADER_TYPES": ("Bearer",),
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=60),
"REFRESH_TOKEN_LIFETIME": timedelta(days=1),
"ROTATE_REFRESH_TOKENS": True,
"BLACKLIST_AFTER_ROTATION": True,
}
4. Add credentials for the providers you want
Only configure the providers you’re using - anything left out is automatically disabled, endpoints included.
# settings.py
# Google needs only the client ID
GOOGLE_CLIENT_ID = "your-google-client-id"
# GitHub needs both
GITHUB_CLIENT_ID = "your-github-client-id"
GITHUB_CLIENT_SECRET = "your-github-client-secret"
5. Register the URLs
Include the base module plus each provider you’re enabling.
# urls.py
from django.urls import path, include
urlpatterns = [
path("api/social-auth/", include("django_social_auth_rest.urls")),
path("api/social-auth/", include("django_social_auth_rest.urls.google")),
path("api/social-auth/", include("django_social_auth_rest.urls.github")),
]
6. Run migrations
python manage.py migrate
No custom auth backends to write, no middleware to register - that’s the full setup.
Optional settings
These all have sensible defaults and only need attention if your project has specific requirements.
| Setting | Default | What it does |
|---|---|---|
SOCIAL_AUTH_THROTTLE_RATE | "10/minute" | Login requests allowed per minute |
SOCIAL_AUTH_STATE_SALT | "social-auth-state-salt" | Salt used to sign GitHub’s OAuth state tokens - change this in production |
SOCIAL_AUTH_STATE_MAX_AGE | 300 | Seconds a state token stays valid before expiring |
SOCIAL_AUTH_USER_DELETED_FIELD | None | Boolean field on your user model marking soft-deleted accounts |
Example requests
Google login
POST /api/social-auth/google/login/
Content-Type: application/json
{ "token": "<google-id-token>" }
GitHub login
POST /api/social-auth/github/login/
Content-Type: application/json
{ "code": "<github-authorization-code>", "state": "<signed-state-token>" }
Both return:
{ "access": "<jwt-access-token>", "refresh": "<jwt-refresh-token>" }
Link and unlink calls return 204 No Content on success.
Signals
| Signal | When it fires |
|---|---|
new_user_registered | A new account is created via social auth for the first time |
login_successful | A user signs in successfully |
link_account_successful | A provider is linked to a user |
unlink_account_successful | A provider is removed from a user |
Each signal passes request, user, and provider.
from django.dispatch import receiver
from django_social_auth_rest.signals import new_user_registered
@receiver(new_user_registered)
def on_new_user(sender, request, user, provider, **kwargs):
print(f"New user {user.email} joined via {provider}")
# send a welcome email, create a profile, etc.
What it’s built with
| Part | What’s used |
|---|---|
| Language | Python 3.12+ |
| Framework | Django 5.0+, Django REST Framework 3.15+ |
| Login standard | OAuth 2.0 |
| Providers | Google Identity Services, GitHub OAuth |
| Tokens | djangorestframework-simplejwt |
Why I built it
Every Django API project I worked on needed social login eventually, and I kept rewriting the same token verification, account-linking, and JWT wiring each time. django-social-auth-rest packages all of that into one library - easy to drop in, safe by default, and built to grow as more providers get added.