An extension to django oauth toolkit to support Dynamic Client Registration RFC7591
Project description
Django OAuth Toolkit DCR
An extension to Django OAuth Toolkit that adds support for OAuth 2.0 Dynamic Client Registration as defined in RFC 7591.
Features
- ✅ RFC 7591 Compliant: Full implementation of OAuth 2.0 Dynamic Client Registration
- ✅ Open Registration Mode: No authentication required for client registration
- ✅ Comprehensive Validation: Validates client metadata, redirect URIs, and grant types
- ✅ Django OAuth Toolkit Integration: Seamlessly works with existing DOT applications
- ✅ Flexible Grant Type Support: Authorization Code, Implicit, Client Credentials, and more
- ✅ Error Handling: RFC-compliant error responses
- ✅ Security Focused: Built-in validations and configurable restrictions
Installation
Install the package using pip:
pip install django-oauth-toolkit-dcr
Requirements
- Python 3.10+
- Django 4.0+
- django-oauth-toolkit 3.0.1+
Quick Start
1. Add to Django Settings
Add the package to your INSTALLED_APPS:
INSTALLED_APPS = [
# ... your other apps
'oauth2_provider',
'oauth_dcr',
]
2. Configure URLs
Add the Dynamic Client Registration endpoint to your URL configuration:
# urls.py
from django.urls import path, include
from oauth_dcr.views import DynamicClientRegistrationView
urlpatterns = [
# Your existing OAuth2 URLs
path('o/', include('oauth2_provider.urls', namespace='oauth2_provider')),
# Dynamic Client Registration endpoint
path('o/register/', DynamicClientRegistrationView.as_view(), name='oauth2_dcr'),
]
3. Run Migrations
Make sure your Django OAuth Toolkit migrations are up to date:
python manage.py migrate
Usage
Client Registration Request
Clients can register themselves by sending a POST request to the registration endpoint:
curl -X POST https://your-server.com/o/register/ \
-H "Content-Type: application/json" \
-d '{
"client_name": "My Amazing App",
"redirect_uris": [
"https://myapp.com/oauth/callback",
"https://myapp.com/oauth/callback2"
],
"grant_types": ["authorization_code"],
"response_types": ["code"],
"scope": "read write",
"client_uri": "https://myapp.com",
"contacts": ["admin@myapp.com"]
}'
Successful Registration Response
{
"client_id": "AbCdEf123456",
"client_secret": "secret_AbCdEf123456789",
"client_id_issued_at": 1625097600,
"client_name": "My Amazing App",
"redirect_uris": [
"https://myapp.com/oauth/callback",
"https://myapp.com/oauth/callback2"
],
"grant_types": ["authorization_code"],
"response_types": ["code"],
"token_endpoint_auth_method": "client_secret_basic"
}
Error Response Examples
Invalid Grant Type:
{
"error": "invalid_client_metadata",
"error_description": "Grant type 'password' is not allowed for dynamic registration"
}
Missing Redirect URIs:
{
"error": "invalid_client_metadata",
"error_description": "redirect_uris required for authorization code grants"
}
HTTPS Required:
{
"error": "invalid_client_metadata",
"error_description": "HTTPS required for redirect URIs in production: http://example.com/callback"
}
Supported Client Metadata
The following client metadata parameters are supported:
| Parameter | Required | Description |
|---|---|---|
client_name |
No | Human-readable name for the client |
redirect_uris |
Conditional* | Array of redirect URIs |
grant_types |
No | Array of grant types (default: ["authorization_code"]) |
response_types |
No | Array of response types |
scope |
No | Space-separated list of scopes |
client_uri |
No | URL of the client's homepage |
contacts |
No | Array of contact email addresses |
token_endpoint_auth_method |
No | Token endpoint authentication method |
*Required for authorization_code, implicit, and hybrid flows.
Supported Grant Types
All RFC 7591 compliant grant types are supported:
authorization_code- Authorization Code Grant ✅ (enabled by default)implicit- Implicit Grant ✅ (enabled by default)refresh_token- Refresh Token Grant ✅ (enabled by default)password- Resource Owner Password Credentials Grant (⚠️ disabled by default - security risk)client_credentials- Client Credentials Grant (⚠️ disabled by default - security risk)urn:ietf:params:oauth:grant-type:jwt-bearer- JWT Bearer Grant (⚠️ disabled by default - security risk)urn:ietf:params:oauth:grant-type:saml2-bearer- SAML 2.0 Bearer Grant (⚠️ disabled by default - security risk)
Configuration
Django OAuth Toolkit Settings
The extension respects your existing Django OAuth Toolkit configuration:
# settings.py
OAUTH2_PROVIDER = {
'ALLOWED_REDIRECT_URI_SCHEMES': ['https', 'http'], # Used for validation
'OIDC_RSA_PRIVATE_KEY': 'your-rsa-key', # For OIDC support
# ... other settings
}
Dynamic Client Registration Settings
Configure DCR-specific settings for enhanced security:
# settings.py
OAUTH_DCR_SETTINGS = {
# Grant types allowed for dynamic registration (RFC 7591 safe defaults)
'ALLOWED_GRANT_TYPES': [
'authorization_code', # Safe for open registration
'implicit', # Part of RFC 7591 (deprecated in OAuth 2.1)
'refresh_token', # Safe - used for token renewal
# 'password', # SECURITY RISK: Allows credential collection
# 'client_credentials', # SECURITY RISK: Machine-to-machine access
# 'urn:ietf:params:oauth:grant-type:jwt-bearer', # SECURITY RISK
# 'urn:ietf:params:oauth:grant-type:saml2-bearer', # SECURITY RISK
],
# Require HTTPS for redirect URIs in production (default: True in production)
'REQUIRE_HTTPS_REDIRECT_URIS': True,
}
Security Rationale for Grant Type Restrictions
| Grant Type | Security Risk | Why Restricted by Default |
|---|---|---|
password |
HIGH | Allows any client to collect user credentials |
client_credentials |
HIGH | Enables machine-to-machine access without user consent |
jwt-bearer |
MEDIUM | Can potentially bypass normal authentication flows |
saml2-bearer |
MEDIUM | Can potentially bypass normal authentication flows |
authorization_code |
LOW | Secure with proper PKCE implementation ✅ |
implicit |
MEDIUM | Deprecated due to token exposure, but part of RFC 7591 ✅ |
refresh_token |
LOW | Safe token renewal mechanism ✅ |
Security Considerations
Since this implements "open" registration mode, the following security measures are strongly recommended:
- Grant Type Restrictions: Only allow safe grant types (default configuration)
- HTTPS Enforcement: Require HTTPS for redirect URIs in production (default)
- Rate Limiting: Use Django rate limiting middleware
- Monitoring: Log all registration attempts
- Cleanup: Implement periodic cleanup of unused clients
- Network Security: Consider IP allowlisting or VPN requirements
Advanced Usage
Custom Validation
You can extend the view to add custom validation:
from oauth_dcr.views import DynamicClientRegistrationView
from django.core.exceptions import ValidationError
class CustomDCRView(DynamicClientRegistrationView):
def _validate_client_metadata(self, metadata):
# Call parent validation first
processed = super()._validate_client_metadata(metadata)
# Add custom validation
if 'client_name' in metadata:
if 'forbidden' in metadata['client_name'].lower():
raise ValidationError("Client name contains forbidden words")
return processed
Rate Limiting Example
Using django-ratelimit:
from django_ratelimit.decorators import ratelimit
from django.utils.decorators import method_decorator
@method_decorator(ratelimit(key='ip', rate='10/h', method='POST'), name='post')
class RateLimitedDCRView(DynamicClientRegistrationView):
pass
API Reference
DynamicClientRegistrationView
Main view class that handles client registration requests.
Methods
post(request)- Handle registration requests_validate_client_metadata(metadata)- Override for custom validation_create_application(metadata)- Override for custom application creation
Testing
Run the tests:
pytest
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Contributions are particularly welcome to implement:
- RFC 7592 Dynamic Client Registration Management Protocol (client configuration endpoint, update/delete operations)
- Additional registration modes (protected, authenticated, administrative registration beyond the current open mode)
- Enhanced security features (rate limiting, audit logging, client attestation)
- OpenID Connect Dynamic Client Registration support
- Security Measures rate limiting
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Related Projects
- Django OAuth Toolkit - The base OAuth 2.0 implementation
- oauthlib - The underlying OAuth library
Support
If you encounter any issues or have questions:
- Check the Issues page
- Create a new issue with detailed information
- For general OAuth questions, refer to the Django OAuth Toolkit documentation
Changelog
v0.1.0 (Initial Release)
- Initial implementation of RFC 7591 Dynamic Client Registration
- Support for open registration mode
- Comprehensive client metadata validation
- Integration with Django OAuth Toolkit Application model
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_oauth_toolkit_dcr-0.1.0.tar.gz.
File metadata
- Download URL: django_oauth_toolkit_dcr-0.1.0.tar.gz
- Upload date:
- Size: 8.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.3 CPython/3.12.8 Windows/11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f5560222fe0e7df95418d57687089ee107434d5d0f4afa3beb81a42934885af5
|
|
| MD5 |
10606d36649d477438483960c1e15beb
|
|
| BLAKE2b-256 |
d33a15ec2e3bc8666457d332ce3cede59fcc3e15a4a13f4b0367c99b1e9fd2da
|
File details
Details for the file django_oauth_toolkit_dcr-0.1.0-py3-none-any.whl.
File metadata
- Download URL: django_oauth_toolkit_dcr-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.3 CPython/3.12.8 Windows/11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cc7e45a47b01ef45a2a476279e5ebbbe716f29be7fc96bf8ba16e18c297b81d1
|
|
| MD5 |
7a3608081f08201a73df789fe1c245fc
|
|
| BLAKE2b-256 |
35206c0fc0663e17e944286d0203b09e3c1084a4eaeaa2ab89b09ef113ac76fb
|