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

management-views.mddocs/

Management Views

Django OAuth Toolkit provides comprehensive web interface views for managing OAuth2 applications and user-authorized tokens. These class-based views integrate with Django's admin system and provide complete CRUD operations.

Capabilities

Application Management Views

Web interface for OAuth2 client application management with full CRUD operations.

class ApplicationList(ListView):
    """
    List view for OAuth2 applications.
    URL: /o/applications/
    
    Shows paginated list of applications owned by the current user.
    Requires user authentication.
    
    Template: oauth2_provider/application_list.html
    Context: applications (queryset of Application objects)
    """
    
    model = Application
    template_name = "oauth2_provider/application_list.html"
    context_object_name = "applications"

class ApplicationDetail(DetailView):
    """
    Detail view for OAuth2 application.
    URL: /o/applications/{pk}/
    
    Shows detailed information about a specific application.
    Only accessible to application owner.
    
    Template: oauth2_provider/application_detail.html
    Context: application (Application object)
    """
    
    model = Application
    template_name = "oauth2_provider/application_detail.html"
    context_object_name = "application"

class ApplicationRegistration(CreateView):
    """
    Create view for registering new OAuth2 applications.
    URL: /o/applications/register/
    
    Form for creating new OAuth2 client applications.
    Automatically assigns current user as application owner.
    
    Template: oauth2_provider/application_registration_form.html
    Form: ApplicationForm
    """
    
    model = Application
    template_name = "oauth2_provider/application_registration_form.html"
    form_class = ApplicationForm

class ApplicationUpdate(UpdateView):
    """
    Update view for OAuth2 applications.
    URL: /o/applications/{pk}/update/
    
    Form for updating existing OAuth2 applications.
    Only accessible to application owner.
    
    Template: oauth2_provider/application_form.html
    Form: ApplicationForm
    """
    
    model = Application
    template_name = "oauth2_provider/application_form.html"
    form_class = ApplicationForm

class ApplicationDelete(DeleteView):
    """
    Delete view for OAuth2 applications.
    URL: /o/applications/{pk}/delete/
    
    Confirmation form for deleting OAuth2 applications.
    Only accessible to application owner.
    
    Template: oauth2_provider/application_confirm_delete.html
    Context: application (Application object)
    """
    
    model = Application
    template_name = "oauth2_provider/application_confirm_delete.html"
    success_url = reverse_lazy("oauth2_provider:list")

Token Management Views

Web interface for users to manage their authorized OAuth2 tokens.

class AuthorizedTokensListView(ListView):
    """
    List view for user's authorized OAuth2 tokens.
    URL: /o/authorized_tokens/
    
    Shows paginated list of access tokens authorized by current user.
    Groups tokens by application and shows token details.
    
    Template: oauth2_provider/authorized-tokens.html
    Context: authorized_tokens (queryset of AccessToken objects)
    """
    
    template_name = "oauth2_provider/authorized-tokens.html"
    context_object_name = "authorized_tokens"
    
    def get_queryset(self):
        """Get access tokens for current user"""

class AuthorizedTokenDeleteView(DeleteView):
    """
    Delete view for revoking authorized tokens.
    URL: /o/authorized_tokens/{pk}/delete/
    
    Allows users to revoke their authorized tokens.
    Revokes both access and refresh tokens.
    
    Template: oauth2_provider/authorized-token-delete.html
    Context: authorized_token (AccessToken object)
    """
    
    template_name = "oauth2_provider/authorized-token-delete.html"
    context_object_name = "authorized_token"
    success_url = reverse_lazy("oauth2_provider:authorized-token-list")

Management URL Patterns

URL patterns for application and token management views.

management_urlpatterns = [
    # Application management views
    path("applications/", views.ApplicationList.as_view(), name="list"),
    path("applications/register/", views.ApplicationRegistration.as_view(), name="register"),
    path("applications/<slug:pk>/", views.ApplicationDetail.as_view(), name="detail"),
    path("applications/<slug:pk>/delete/", views.ApplicationDelete.as_view(), name="delete"),
    path("applications/<slug:pk>/update/", views.ApplicationUpdate.as_view(), name="update"),
    # Token management views
    path("authorized_tokens/", views.AuthorizedTokensListView.as_view(), name="authorized-token-list"),
    path(
        "authorized_tokens/<slug:pk>/delete/",
        views.AuthorizedTokenDeleteView.as_view(),
        name="authorized-token-delete",
    ),
]

Usage Examples

URL Configuration

# urls.py
from django.urls import path, include

urlpatterns = [
    # Include OAuth2 management URLs
    path('o/', include('oauth2_provider.urls', namespace='oauth2_provider')),
]

# This provides these management URLs:
# /o/applications/ - List applications
# /o/applications/register/ - Register new application  
# /o/applications/{id}/ - View application details
# /o/applications/{id}/update/ - Update application
# /o/applications/{id}/delete/ - Delete application
# /o/authorized_tokens/ - List authorized tokens
# /o/authorized_tokens/{id}/delete/ - Revoke token

Custom Application Management

from oauth2_provider.views.application import ApplicationRegistration
from oauth2_provider.forms import ApplicationForm
from django import forms

class CustomApplicationForm(ApplicationForm):
    """Custom form with additional fields"""
    
    description = forms.CharField(
        max_length=500,
        required=False,
        widget=forms.Textarea,
        help_text="Describe your application"
    )
    
    class Meta(ApplicationForm.Meta):
        fields = ApplicationForm.Meta.fields + ['description']

class CustomApplicationRegistration(ApplicationRegistration):
    """Custom registration view with additional fields"""
    
    form_class = CustomApplicationForm
    template_name = "myapp/custom_application_form.html"
    
    def form_valid(self, form):
        """Add custom processing before saving"""
        # Custom logic here
        return super().form_valid(form)

# URL configuration
# path('custom/register/', CustomApplicationRegistration.as_view(), name='custom_register')

Template Customization

<!-- templates/oauth2_provider/application_list.html -->
{% extends "base.html" %}

{% block content %}
<h1>My OAuth2 Applications</h1>

<a href="{% url 'oauth2_provider:register' %}" class="btn btn-primary">
    Register New Application
</a>

<div class="applications">
    {% for application in applications %}
    <div class="application-card">
        <h3>{{ application.name }}</h3>
        <p><strong>Client ID:</strong> {{ application.client_id }}</p>
        <p><strong>Type:</strong> {{ application.get_client_type_display }}</p>
        <p><strong>Grant Type:</strong> {{ application.get_authorization_grant_type_display }}</p>
        
        <div class="actions">
            <a href="{% url 'oauth2_provider:detail' application.pk %}">View</a>
            <a href="{% url 'oauth2_provider:update' application.pk %}">Edit</a>
            <a href="{% url 'oauth2_provider:delete' application.pk %}">Delete</a>
        </div>
    </div>
    {% empty %}
    <p>No applications registered yet.</p>
    {% endfor %}
</div>
{% endblock %}

Access Control

from oauth2_provider.views.application import ApplicationDetail
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.exceptions import PermissionDenied

class SecureApplicationDetail(LoginRequiredMixin, ApplicationDetail):
    """Application detail view with enhanced security"""
    
    def get_object(self, queryset=None):
        """Ensure user can only access their own applications"""
        obj = super().get_object(queryset)
        if obj.user != self.request.user:
            raise PermissionDenied("You can only view your own applications")
        return obj

class AdminApplicationList(ApplicationList):
    """Admin view to see all applications (requires staff permission)"""
    
    def get_queryset(self):
        """Show all applications for staff users"""
        if not self.request.user.is_staff:
            raise PermissionDenied("Staff access required")
        return Application.objects.all()

Token Management Integration

from oauth2_provider.views.token import AuthorizedTokensListView
from django.db.models import Q

class EnhancedTokenListView(AuthorizedTokensListView):
    """Enhanced token list with filtering and search"""
    
    def get_queryset(self):
        """Add filtering and search capabilities"""
        queryset = super().get_queryset()
        
        # Filter by application
        app_filter = self.request.GET.get('application')
        if app_filter:
            queryset = queryset.filter(application__name__icontains=app_filter)
            
        # Filter by scope
        scope_filter = self.request.GET.get('scope')
        if scope_filter:
            queryset = queryset.filter(scope__icontains=scope_filter)
            
        # Filter active tokens only
        if self.request.GET.get('active_only'):
            from django.utils import timezone
            queryset = queryset.filter(expires__gt=timezone.now())
            
        return queryset.order_by('-created')
    
    def get_context_data(self, **kwargs):
        """Add filter context"""
        context = super().get_context_data(**kwargs)
        context['applications'] = Application.objects.filter(
            accesstoken__user=self.request.user
        ).distinct()
        return context

API Integration

from oauth2_provider.views.application import ApplicationList
from django.http import JsonResponse
from django.views.generic import View

class ApplicationAPIView(View):
    """API endpoint for application management"""
    
    def get(self, request):
        """Return applications as JSON"""
        if not request.user.is_authenticated:
            return JsonResponse({'error': 'Authentication required'}, status=401)
            
        applications = Application.objects.filter(user=request.user)
        data = []
        
        for app in applications:
            data.append({
                'id': app.pk,
                'name': app.name,
                'client_id': app.client_id,
                'client_type': app.client_type,
                'authorization_grant_type': app.authorization_grant_type,
                'created': app.created.isoformat(),
            })
            
        return JsonResponse({'applications': data})

class TokenAPIView(View):
    """API endpoint for token management"""
    
    def get(self, request):
        """Return user's tokens as JSON"""
        if not request.user.is_authenticated:
            return JsonResponse({'error': 'Authentication required'}, status=401)
            
        tokens = AccessToken.objects.filter(user=request.user)
        data = []
        
        for token in tokens:
            data.append({
                'id': token.pk,
                'application': token.application.name,
                'scope': token.scope,
                'expires': token.expires.isoformat(),
                'is_expired': token.is_expired(),
            })
            
        return JsonResponse({'tokens': data})
    
    def delete(self, request, token_id):
        """Revoke specific token"""
        if not request.user.is_authenticated:
            return JsonResponse({'error': 'Authentication required'}, status=401)
            
        try:
            token = AccessToken.objects.get(pk=token_id, user=request.user)
            token.revoke()
            return JsonResponse({'message': 'Token revoked successfully'})
        except AccessToken.DoesNotExist:
            return JsonResponse({'error': 'Token not found'}, status=404)

Bulk Operations

from oauth2_provider.views.token import AuthorizedTokensListView
from django.shortcuts import redirect
from django.contrib import messages

class BulkTokenManagementView(AuthorizedTokensListView):
    """Token list view with bulk operations"""
    
    def post(self, request, *args, **kwargs):
        """Handle bulk operations"""
        action = request.POST.get('action')
        token_ids = request.POST.getlist('selected_tokens')
        
        if not token_ids:
            messages.error(request, 'No tokens selected')
            return redirect('oauth2_provider:authorized-token-list')
            
        tokens = AccessToken.objects.filter(
            pk__in=token_ids,
            user=request.user
        )
        
        if action == 'revoke_selected':
            count = 0
            for token in tokens:
                token.revoke()
                count += 1
            messages.success(request, f'{count} tokens revoked successfully')
            
        elif action == 'revoke_expired':
            expired_tokens = tokens.filter(expires__lt=timezone.now())
            count = expired_tokens.count()
            for token in expired_tokens:
                token.revoke()
            messages.success(request, f'{count} expired tokens revoked')
            
        return redirect('oauth2_provider:authorized-token-list')

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