Skip to content

Welcome to Django Social Auth REST

Plug-and-play social authentication for Django REST Framework. Sign in with social providers, link accounts, and issue JWT tokens in minutes.

Every Django project ends up needing the same thing eventually: let users sign in with Google or GitHub, hand back a token, and don’t break anything when they later connect a second provider. Getting that right means writing CSRF-safe state handling, normalizing two very different OAuth flows, issuing JWTs, and untangling account-linking edge cases - by hand, every time.

django-social-auth-rest does all of that for you. Add it to INSTALLED_APPS, drop in your provider credentials, and you’ve got production-ready social login speaking the same JWT language as the rest of your API.

Provider-abstracted login

One consistent JWT response shape for every provider. Sign in with Google or GitHub through the same pattern - swap providers without rewriting your client.

Account linking, done right

Users can connect or disconnect social accounts from an existing profile at any time, with unique constraints that keep one social identity tied to one user.

JWT-first, not bolted on

Built directly on djangorestframework-simplejwt. Access and refresh tokens come back from every login, link, and signup call - no extra wiring.

CSRF-safe by design

The OAuth flow uses signed, time-limited state tokens out of the box, so you don’t need to implement custom CSRF protection for the authorization redirect flow.

Abuse-resistant

Every auth endpoint ships with configurable rate limiting (SOCIAL_AUTH_THROTTLE_RATE), so a single misbehaving client can’t hammer your login endpoint.

Hooks into your app's logic

Django signals fire on every key event - new_user_registered, login_successful, link_account_successful, unlink_account_successful - so welcome emails and analytics are a @receiver away.

  1. Install it.

    Terminal window
    pip install django-social-auth-rest
  2. Register the app and JWT auth.

    # settings.py
    INSTALLED_APPS = [
    # ...
    "rest_framework",
    "django_social_auth_rest",
    ]
    REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": (
    "rest_framework_simplejwt.authentication.JWTAuthentication",
    ),
    }
    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,
    }
  3. Configure the Signup Serializer for remove duplicates

    class SignupSerializer(serializers.Serializer):
    ...
    def validate(self, attrs):
    attrs = super().validate(attrs)
    email = attrs.get("email", "").strip().lower()
    if SocialAccountLinked.objects.filter(email_linked=email).exists():
    raise serializers.ValidationError( {"email": ["An account already exists for this email."]} )
    return attrs

    It is important to validate the email in the signup serializer to avoid duplicate accounts being created for the same email address. This ensures that if a user tries to sign up with an email that is already linked to a social account, they will receive a validation error.

  4. Set a real state-signing salt.

    # settings.py
    SOCIAL_AUTH_STATE_SALT = "a-long-random-secret-value"
  5. Drop in credentials for the providers you want.

    # settings.py
    GITHUB_CLIENT_ID = "your-github-client-id"
    GITHUB_CLIENT_SECRET = "your-github-client-secret"
    GOOGLE_CLIENT_ID = "your-google-client-id"
    # ... add other providers as needed

    Providers without credentials stay disabled automatically - no dead endpoints to guard against.

  6. Wire up the URLs and migrate.

    # urls.py
    urlpatterns = [
    path("api/social-auth/", include("django_social_auth_rest.urls")),
    path("api/social-auth/", include("django_social_auth_rest.urls.github")),
    path("api/social-auth/", include("django_social_auth_rest.urls.google")),
    # ... add other providers as needed
    ]
  7. Run migrations.

    Terminal window
    python manage.py migrate
POST /api/social-auth/github/login/
Content-Type: application/json
{
"code": "<AUTHORIZATION_CODE>",
"state": "<SIGNED_STATE_TOKEN>"
}
{
"access": "<JWT_ACCESS_TOKEN>",
"refresh": "<JWT_REFRESH_TOKEN>"
}

Linking, unlinking, and checking which providers a user has connected follow the exact same shape - every endpoint returns JWTs or a clean 204 No Content.