
Security News
Node.js Moves Toward Stable TypeScript Support with Amaro 1.0
Amaro 1.0 lays the groundwork for stable TypeScript support in Node.js, bringing official .ts loading closer to reality.
django-oauth-toolkit-dcr
Advanced tools
An extension to django oauth toolkit to support Dynamic Client Registration RFC7591
An extension to Django OAuth Toolkit that adds support for OAuth 2.0 Dynamic Client Registration as defined in RFC 7591.
Install the package using pip:
pip install django-oauth-toolkit-dcr
Add the package to your INSTALLED_APPS
:
INSTALLED_APPS = [
# ... your other apps
'oauth2_provider',
'oauth_dcr',
]
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'),
]
Make sure your Django OAuth Toolkit migrations are up to date:
python manage.py migrate
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"]
}'
{
"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"
}
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"
}
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.
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)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
}
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,
}
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 ✅ |
Since this implements "open" registration mode, the following security measures are strongly recommended:
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
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
Main view class that handles client registration requests.
post(request)
- Handle registration requests_validate_client_metadata(metadata)
- Override for custom validation_create_application(metadata)
- Override for custom application creationRun the tests:
pytest
Contributions are welcome! Please feel free to submit a Pull Request.
Contributions are particularly welcome to implement:
git checkout -b feature/amazing-feature
)git commit -m 'Add some amazing feature'
)git push origin feature/amazing-feature
)This project is licensed under the MIT License - see the LICENSE file for details.
If you encounter any issues or have questions:
FAQs
An extension to django oauth toolkit to support Dynamic Client Registration RFC7591
We found that django-oauth-toolkit-dcr demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Amaro 1.0 lays the groundwork for stable TypeScript support in Node.js, bringing official .ts loading closer to reality.
Research
A deceptive PyPI package posing as an Instagram growth tool collects user credentials and sends them to third-party bot services.
Product
Socket now supports pylock.toml, enabling secure, reproducible Python builds with advanced scanning and full alignment with PEP 751's new standard.