drf-oauth-toolkit
is a flexible and lightweight OAuth2 integration library for Django Rest Framework (DRF), designed to simplify the process of adding OAuth2 support to your DRF projects.
- β Plug-and-play OAuth2 integration for DRF
- β Supports multiple OAuth providers (Google, Facebook, etc.)
- β Built-in token management and CSRF protection
- β Customizable and extensible service classes
pip install drf-oauth-toolkit
Add drf_oauth_toolkit
to your settings.py
:
INSTALLED_APPS = [
...
"drf_oauth_toolkit",
]
- Configure OAuth credentials in your Django settings:
OAUTH_CREDENTIALS = {
"host": "http://127.0.0.1:8000",
"encryption_key": "Xcub4xIr71H3VR_PxDQdXAT39H9lM9nE2A0GQBg38Xo=",
"google": {
"client_id": "your google client id",
"client_secret": "your google client secert",
"callback_url": "google-callback",
},
}
- Extend the base service class to integrate a provider:
from drf_oauth_toolkit.views.google_views import GoogleOAuth2CallbackApi, GoogleOAuth2RedirectApi
urlpatterns = [
...
path("oauth2/google/login", GoogleOAuth2RedirectApi.as_view(), name="google-login"),
path("oauth2/google/callback", GoogleOAuth2CallbackApi.as_view(), name="google-callback"), # sure the url name matches the one in the settings
]
The OAuth2 flow for the drf-oauth-toolkit
is visualized in the following diagram. It highlights the key steps involved in the authentication and token exchange process:
- User Initiates Login: The user begins the login process by clicking on an OAuth provider button (e.g., Google Login).
- Redirect to OAuth Provider: The user is redirected to the OAuth provider's authorization page to authenticate.
- Authorization Grant: The OAuth provider prompts the user to approve the requested scopes and grant access.
- Authorization Code: After approval, the OAuth provider redirects back to the callback URL with an authorization code.
- Token Exchange: The authorization code is exchanged for access and refresh tokens via the provider's token endpoint.
- Token Storage: The tokens are securely stored in the backend for future use.
- Authenticated Access: The user gains authenticated access to the application.
This process ensures secure integration of OAuth2 providers with Django Rest Framework applications while allowing full flexibility for customization.
In my experience, OAuth integration has become a standard requirement across modern software projects. Whether you're integrating with Google, Facebook, or other OAuth providers, there are already some outstanding libraries available for Django and Django Rest Framework, such as:
- django-oauth-toolkit β A full-featured OAuth2 provider for Django.
- social-auth-app-django β A powerful social authentication library supporting multiple providers.
- dj-rest-auth β A drop-in solution for user registration and social authentication.
However, the challenge I aim to solve with drf-oauth-toolkit
is the ease of use and flexibility. Many existing solutions assume a rigid workflow for how you should handle tokens and user management, often leading to challenges when working with DRF or when the library doesnβt align with your token handling requirements.
- Complex Setup: Some libraries require extensive setup with limited flexibility.
- Token Management Assumptions: Many solutions assume how tokens should be stored and used, which may not fit every project.
- DRF Integration: Some packages aren't well-optimized for Django Rest Framework out of the box.
drf-oauth-toolkit
aims to simplify the OAuth integration process while maintaining full control and flexibility over how tokens are stored, validated, and extended. The core design principle is customizability β you can override and extend methods according to your projectβs needs.
If you simply want to store tokens after a successful OAuth flow, you should not need to do anything, but in case you have a custom user model you can use something like below example:
from django.contrib.auth import get_user_model
from drf_oauth_toolkit.models import OAuth2Token, ServiceChoices
from drf_oauth_toolkit.services.google import GoogleOAuth2Service
from drf_oauth_toolkit.views.base import OAuthCallbackApiBase
User = get_user_model()
class GoogleOAuth2CallbackApi(OAuthCallbackApiBase):
oauth_service_class = GoogleOAuth2Service
session_state_key = "google_oauth_state"
user_info_email_field = "email"
user_info_first_name_field = "given_name"
user_info_last_name_field = "family_name"
def update_account(self, user, oauth_tokens):
"""
Update or create a user account with the given OAuth tokens.
"""
if user is None:
user_info = self.oauth_service_class().get_user_info(oauth_tokens=oauth_tokens)
user = self.create_user_from_oauth(user_info)
OAuth2Token.objects.update_or_create_token(
user=user, service_name=ServiceChoices.GOOGLE, oauth_tokens=oauth_tokens
)
def create_user_from_oauth(self, user_info):
"""
Create a new user based on the information retrieved from the OAuth service.
"""
email = user_info.get(self.user_info_email_field)
first_name = user_info.get(self.user_info_first_name_field, "")
last_name = user_info.get(self.user_info_last_name_field, "")
user, _ = User.objects.get_or_create(
email=email,
defaults={
"first_name": first_name,
"last_name": last_name,
"username": email.split("@")[0],
},
)
return user
You can easily extend the base service for different OAuth providers. For example, handling YouTube OAuth integration:
class YouTubeOAuthService(GoogleOAuth2Service):
API_URI_NAME = "youtube_callback"
SCOPES = [
"https://www.googleapis.com/auth/youtube.readonly",
"https://www.googleapis.com/auth/userinfo.email",
]
def fetch_channel_info(self, oauth_tokens: OAuthTokens) -> Dict[str, Any]:
self._ensure_valid_token(oauth_tokens)
headers = {"Authorization": f"Bearer {oauth_tokens.access_token}"}
response = requests.get(
"https://www.googleapis.com/youtube/v3/channels",
headers=headers,
params={"part": "snippet,contentDetails,statistics", "mine": "true"},
)
response.raise_for_status()
return response.json()
- Improved Documentation: Adding more inline code documentation and examples for clarity.
- Expanded Provider Support: Adding support for additional OAuth providers like Facebook and Microsoft.
- Enhanced Token Management: Providing built-in support for token rotation and expiration handling.
Run tests using pytest
:
pytest
Contributions are welcome! If you'd like to contribute:
- Fork the repository
- Create a feature branch (
git checkout -b feature-branch
) - Commit your changes (
git commit -m 'Add feature'
) - Push the branch (
git push origin feature-branch
) - Open a pull request
For major changes, please open an issue first to discuss your ideas.
This project is licensed under the MIT License. See the LICENSE
file for more details.
For questions and suggestions, feel free to reach out via GitHub Issues.