CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-django-oauth-toolkit

OAuth2 Provider for Django web applications with complete server functionality, token management, and authorization endpoints.

Pending
Overview
Eval results
Files

view-protection.mddocs/

View Protection

Django OAuth Toolkit provides decorators and middleware for protecting Django views with OAuth2 authentication and scope-based authorization. These tools integrate seamlessly with Django's view system and provide flexible access control.

Capabilities

Protected Resource Decorator

Basic OAuth2 authentication decorator that protects views by requiring valid access tokens.

def protected_resource(scopes=None, validator_cls=OAuth2Validator, server_cls=Server):
    """
    Decorator to protect views with OAuth2 authentication.
    
    Args:
        scopes: List of required OAuth2 scopes (optional)
        validator_cls: Custom OAuth2 validator class
        server_cls: Custom OAuth2 server class
        
    Returns:
        Decorated view function that requires OAuth2 authentication
        
    Usage:
        @protected_resource()
        def my_view(request):
            # Access token required to reach here
            user = request.resource_owner  # User from token or None
            return JsonResponse({'user': user.username if user else None})
            
        @protected_resource(scopes=['read'])
        def read_data(request):
            # Requires 'read' scope
            return JsonResponse({'data': 'protected content'})
    """

Read/Write Protected Resource Decorator

OAuth2 decorator with automatic read/write scope assignment based on HTTP method.

def rw_protected_resource(scopes=None, validator_cls=OAuth2Validator, server_cls=Server):
    """
    Decorator that automatically assigns read/write scopes based on HTTP method.
    GET, HEAD, OPTIONS methods require 'read' scope.
    All other methods require 'write' scope.
    
    Args:
        scopes: Additional required scopes beyond read/write
        validator_cls: Custom OAuth2 validator class
        server_cls: Custom OAuth2 server class
        
    Returns:
        Decorated view function with automatic scope assignment
        
    Usage:
        @rw_protected_resource()
        def api_endpoint(request):
            # GET requests need 'read' scope
            # POST/PUT/DELETE requests need 'write' scope
            if request.method == 'POST':
                return JsonResponse({'created': True})
            return JsonResponse({'data': 'content'})
    """

Generic Protected Views

Class-based views that provide OAuth2 protection with various scope configurations.

class ProtectedResourceView(View):
    """
    Basic OAuth2 protected view requiring valid access token.
    
    Attributes:
        required_scopes: List of required OAuth2 scopes
        raise_exception: Whether to raise exception on auth failure
        server_class: OAuth2 server class to use
        validator_class: OAuth2 validator class to use
    """
    
    required_scopes = []
    raise_exception = False
    server_class = Server
    validator_class = OAuth2Validator

class ScopedProtectedResourceView(ProtectedResourceView):
    """
    OAuth2 protected view with specific scope requirements.
    Subclasses must define required_scopes attribute.
    """
    
    required_scopes = None  # Must be overridden

class ReadWriteScopedResourceView(ProtectedResourceView):
    """
    OAuth2 protected view with automatic read/write scope assignment.
    Safe methods (GET, HEAD, OPTIONS) require read scope.
    Unsafe methods require write scope.
    """
    
    def get_scopes(self, request):
        """
        Get required scopes based on request method.
        
        Returns:
            List of scopes required for this request
        """

class ClientProtectedResourceView(ProtectedResourceView):
    """
    OAuth2 protected view for client credentials flow.
    Designed for server-to-server authentication.
    """

class ClientProtectedScopedResourceView(ClientProtectedResourceView):
    """
    OAuth2 protected view for client credentials with specific scopes.
    """
    
    required_scopes = None  # Must be overridden

OAuth2 Token Middleware

Django middleware that adds OAuth2 token information to requests.

class OAuth2TokenMiddleware:
    """
    Middleware that processes OAuth2 tokens and adds token info to request.
    
    Adds the following attributes to HttpRequest:
        - oauth2_error: Dict containing OAuth2 error information if any
        - resource_owner: User associated with the token (if valid)
        
    Should be added to MIDDLEWARE setting in Django configuration.
    """
    
    def __init__(self, get_response):
        """Initialize middleware with Django response handler"""
    
    def __call__(self, request):
        """Process request and add OAuth2 token information"""

Usage Examples

Basic View Protection

from oauth2_provider.decorators import protected_resource
from django.http import JsonResponse

@protected_resource()
def protected_api(request):
    """View requiring any valid OAuth2 token"""
    return JsonResponse({
        'message': 'Hello authenticated user!',
        'user': request.resource_owner.username if request.resource_owner else 'Anonymous'
    })

@protected_resource(scopes=['read'])
def read_only_api(request):
    """View requiring 'read' scope"""
    return JsonResponse({'data': 'This is read-only data'})

@protected_resource(scopes=['write'])
def write_api(request):
    """View requiring 'write' scope"""
    if request.method == 'POST':
        return JsonResponse({'created': True})
    return JsonResponse({'error': 'Method not allowed'}, status=405)

Read/Write Scope Views

from oauth2_provider.decorators import rw_protected_resource

@rw_protected_resource()
def auto_scope_api(request):
    """
    Automatically assigns scopes:
    - GET/HEAD/OPTIONS: requires 'read' scope
    - POST/PUT/DELETE/PATCH: requires 'write' scope
    """
    if request.method == 'GET':
        return JsonResponse({'data': 'Retrieved data'})
    elif request.method == 'POST':
        return JsonResponse({'message': 'Data created'})
    elif request.method == 'PUT':
        return JsonResponse({'message': 'Data updated'})
    elif request.method == 'DELETE':
        return JsonResponse({'message': 'Data deleted'})

@rw_protected_resource(scopes=['admin'])
def admin_api(request):
    """Requires both read/write scopes AND admin scope"""
    return JsonResponse({'message': 'Admin operation completed'})

Class-Based Protected Views

from oauth2_provider.views.generic import (
    ProtectedResourceView, 
    ScopedProtectedResourceView,
    ReadWriteScopedResourceView
)
from django.http import JsonResponse

class BasicProtectedView(ProtectedResourceView):
    """Basic OAuth2 protected view"""
    
    def get(self, request):
        return JsonResponse({
            'user': request.resource_owner.username if request.resource_owner else None
        })

class AdminOnlyView(ScopedProtectedResourceView):
    """View requiring admin scope"""
    required_scopes = ['admin']
    
    def get(self, request):
        return JsonResponse({'message': 'Admin access granted'})

class AutoScopeView(ReadWriteScopedResourceView):
    """View with automatic read/write scope assignment"""
    
    def get(self, request):
        # Requires 'read' scope
        return JsonResponse({'data': 'Read operation'})
    
    def post(self, request):
        # Requires 'write' scope
        return JsonResponse({'message': 'Write operation'})

Custom Authentication Logic

from oauth2_provider.decorators import protected_resource
from oauth2_provider.oauth2_validators import OAuth2Validator
from oauthlib.oauth2 import Server

class CustomValidator(OAuth2Validator):
    """Custom OAuth2 validator with additional business logic"""
    
    def validate_scopes(self, client_id, scopes, client, request, *args, **kwargs):
        # Custom scope validation logic
        return super().validate_scopes(client_id, scopes, client, request, *args, **kwargs)

@protected_resource(
    scopes=['api'], 
    validator_cls=CustomValidator,
    server_cls=Server
)
def custom_protected_view(request):
    """View with custom validator and server classes"""
    return JsonResponse({'message': 'Custom authentication successful'})

Middleware Configuration

# settings.py
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'oauth2_provider.middleware.OAuth2TokenMiddleware',  # Add OAuth2 middleware
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

Error Handling

from oauth2_provider.decorators import protected_resource
from django.http import JsonResponse, HttpResponseForbidden

@protected_resource(scopes=['read'])
def error_handling_view(request):
    """View demonstrating error handling"""
    try:
        # Your protected logic here
        return JsonResponse({'data': 'success'})
    except Exception as e:
        return JsonResponse({'error': str(e)}, status=500)

# OAuth2 errors are automatically handled:
# - Missing token: HTTP 401 Unauthorized
# - Invalid token: HTTP 401 Unauthorized  
# - Insufficient scopes: HTTP 403 Forbidden
# - Expired token: HTTP 401 Unauthorized

Integration with Custom User Models

from oauth2_provider.decorators import protected_resource
from django.contrib.auth import get_user_model

User = get_user_model()

@protected_resource()
def user_profile_view(request):
    """Access custom user model through OAuth2 token"""
    user = request.resource_owner
    if user:
        return JsonResponse({
            'id': user.id,
            'username': user.username,
            'email': user.email,
            # Access custom user fields
            'custom_field': getattr(user, 'custom_field', None)
        })
    return JsonResponse({'error': 'No user found'}, status=400)

Install with Tessl CLI

npx tessl i tessl/pypi-django-oauth-toolkit

docs

drf-integration.md

index.md

management-commands.md

management-views.md

models.md

oauth2-endpoints.md

oidc.md

settings.md

view-protection.md

tile.json