Authentication and Authorization

Authentication Views

Django provides built-in authentication views for common authentication workflows like login, logout, password change, and password reset. Understanding how to use and customize these views enables you to implement secure authentication flows that meet your application's specific requirements.

Authentication Views

Django provides built-in authentication views for common authentication workflows like login, logout, password change, and password reset. Understanding how to use and customize these views enables you to implement secure authentication flows that meet your application's specific requirements.

Built-in Authentication Views

Django's Authentication View Classes

# Django's built-in authentication views
from django.contrib.auth.views import (
    LoginView, LogoutView, PasswordChangeView, PasswordChangeDoneView,
    PasswordResetView, PasswordResetDoneView, PasswordResetConfirmView,
    PasswordResetCompleteView
)
from django.urls import path, reverse_lazy
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib import messages

class AuthenticationViewOverview:
    """Overview of Django's built-in authentication views"""
    
    @staticmethod
    def built_in_views_summary():
        """Summary of all built-in authentication views"""
        
        views_summary = {
            'LoginView': {
                'purpose': 'Handle user login',
                'template': 'registration/login.html',
                'success_url': 'LOGIN_REDIRECT_URL setting',
                'form_class': 'AuthenticationForm'
            },
            'LogoutView': {
                'purpose': 'Handle user logout',
                'template': 'registration/logged_out.html',
                'success_url': 'LOGOUT_REDIRECT_URL setting',
                'form_class': None
            },
            'PasswordChangeView': {
                'purpose': 'Change user password',
                'template': 'registration/password_change_form.html',
                'success_url': 'password_change_done',
                'form_class': 'PasswordChangeForm'
            },
            'PasswordChangeDoneView': {
                'purpose': 'Password change success page',
                'template': 'registration/password_change_done.html',
                'success_url': None,
                'form_class': None
            },
            'PasswordResetView': {
                'purpose': 'Request password reset',
                'template': 'registration/password_reset_form.html',
                'success_url': 'password_reset_done',
                'form_class': 'PasswordResetForm'
            },
            'PasswordResetDoneView': {
                'purpose': 'Password reset request confirmation',
                'template': 'registration/password_reset_done.html',
                'success_url': None,
                'form_class': None
            },
            'PasswordResetConfirmView': {
                'purpose': 'Confirm password reset with token',
                'template': 'registration/password_reset_confirm.html',
                'success_url': 'password_reset_complete',
                'form_class': 'SetPasswordForm'
            },
            'PasswordResetCompleteView': {
                'purpose': 'Password reset completion page',
                'template': 'registration/password_reset_complete.html',
                'success_url': None,
                'form_class': None
            }
        }
        
        return views_summary
    
    @staticmethod
    def basic_url_configuration():
        """Basic URL configuration for authentication views"""
        
        # Method 1: Use Django's built-in auth URLs
        urlpatterns_builtin = [
            path('accounts/', include('django.contrib.auth.urls')),
        ]
        
        # This includes all these URLs:
        # accounts/login/ [name='login']
        # accounts/logout/ [name='logout']
        # accounts/password_change/ [name='password_change']
        # accounts/password_change/done/ [name='password_change_done']
        # accounts/password_reset/ [name='password_reset']
        # accounts/password_reset/done/ [name='password_reset_done']
        # accounts/reset/<uidb64>/<token>/ [name='password_reset_confirm']
        # accounts/reset/done/ [name='password_reset_complete']
        
        # Method 2: Define individual views
        urlpatterns_individual = [
            path('login/', LoginView.as_view(), name='login'),
            path('logout/', LogoutView.as_view(), name='logout'),
            path('password_change/', PasswordChangeView.as_view(), name='password_change'),
            path('password_change/done/', PasswordChangeDoneView.as_view(), name='password_change_done'),
            path('password_reset/', PasswordResetView.as_view(), name='password_reset'),
            path('password_reset/done/', PasswordResetDoneView.as_view(), name='password_reset_done'),
            path('reset/<uidb64>/<token>/', PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
            path('reset/done/', PasswordResetCompleteView.as_view(), name='password_reset_complete'),
        ]
        
        return urlpatterns_builtin, urlpatterns_individual

Let me continue with the rest of the content:

<function_calls> content/09.authentication-and-authorization/06.authentication-views.mdustom Authentication Views

Custom Login Views

# Custom login view implementations
from django.contrib.auth.views import LoginView
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth import login
from django.shortcuts import render, redirect
from django.contrib import messages
from django.urls import reverse_lazy
from django.utils.decorators import method_decorator
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_protect
from django.views.decorators.debug import sensitive_post_parameters

class CustomLoginView(LoginView):
    """Enhanced login view with additional features"""
    
    template_name = 'auth/login.html'
    form_class = AuthenticationForm
    redirect_authenticated_user = True
    
    @method_decorator(sensitive_post_parameters())
    @method_decorator(csrf_protect)
    @method_decorator(never_cache)
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)
    
    def get_success_url(self):
        """Determine where to redirect after successful login"""
        
        # Check for 'next' parameter
        next_url = self.request.POST.get('next') or self.request.GET.get('next')
        
        if next_url:
            return next_url
        
        # Redirect based on user type
        user = self.request.user
        
        if user.is_superuser:
            return reverse_lazy('admin:index')
        elif user.is_staff:
            return reverse_lazy('staff_dashboard')
        elif user.groups.filter(name='Editors').exists():
            return reverse_lazy('editor_dashboard')
        else:
            return reverse_lazy('user_dashboard')
    
    def form_valid(self, form):
        """Handle successful login"""
        
        response = super().form_valid(form)
        
        user = form.get_user()
        
        # Log successful login
        import logging
        logger = logging.getLogger('auth')
        logger.info(f"User {user.username} logged in from {self.request.META.get('REMOTE_ADDR')}")
        
        # Set session data
        self.request.session['login_timestamp'] = timezone.now().isoformat()
        self.request.session['user_agent'] = self.request.META.get('HTTP_USER_AGENT', '')[:200]
        
        # Handle "Remember Me" functionality
        remember_me = self.request.POST.get('remember_me')
        if remember_me:
            # Set session to expire when browser closes (default)
            self.request.session.set_expiry(0)
        else:
            # Set session to expire in 1 hour
            self.request.session.set_expiry(3600)
        
        # Add success message
        messages.success(
            self.request, 
            f'Welcome back, {user.get_full_name() or user.username}!'
        )
        
        # Update last login timestamp
        user.last_login = timezone.now()
        user.save(update_fields=['last_login'])
        
        return response
    
    def form_invalid(self, form):
        """Handle failed login attempt"""
        
        response = super().form_invalid(form)
        
        # Log failed login attempt
        username = form.cleaned_data.get('username', 'unknown')
        
        import logging
        logger = logging.getLogger('auth')
        logger.warning(
            f"Failed login attempt for username: {username} "
            f"from {self.request.META.get('REMOTE_ADDR')}"
        )
        
        # Implement rate limiting (basic example)
        from django.core.cache import cache
        
        ip_address = self.request.META.get('REMOTE_ADDR')
        cache_key = f"failed_login_{ip_address}"
        
        failed_attempts = cache.get(cache_key, 0) + 1
        cache.set(cache_key, failed_attempts, 300)  # 5 minutes
        
        if failed_attempts >= 5:
            messages.error(
                self.request,
                "Too many failed login attempts. Please try again in 5 minutes."
            )
        
        return response
    
    def get_context_data(self, **kwargs):
        """Add additional context to template"""
        
        context = super().get_context_data(**kwargs)
        
        context.update({
            'site_name': 'Your Site Name',
            'allow_registration': True,
            'social_login_enabled': True,
            'password_reset_enabled': True,
        })
        
        return context

class AjaxLoginView(LoginView):
    """Login view that supports AJAX requests"""
    
    def form_valid(self, form):
        """Handle successful AJAX login"""
        
        if self.request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            login(self.request, form.get_user())
            
            return JsonResponse({
                'success': True,
                'message': 'Login successful',
                'redirect_url': self.get_success_url()
            })
        
        return super().form_valid(form)
    
    def form_invalid(self, form):
        """Handle failed AJAX login"""
        
        if self.request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return JsonResponse({
                'success': False,
                'errors': form.errors,
                'message': 'Login failed'
            })
        
        return super().form_invalid(form)

# Function-based login view
def custom_login_view(request):
    """Custom function-based login view"""
    
    if request.user.is_authenticated:
        return redirect('dashboard')
    
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        remember_me = request.POST.get('remember_me')
        
        # Authenticate user
        user = authenticate(request, username=username, password=password)
        
        if user is not None:
            if user.is_active:
                # Log in user
                login(request, user)
                
                # Handle remember me
                if not remember_me:
                    request.session.set_expiry(0)  # Browser session
                
                # Add success message
                messages.success(request, f'Welcome, {user.get_full_name() or user.username}!')
                
                # Redirect to next or default
                next_url = request.POST.get('next') or request.GET.get('next')
                return redirect(next_url or 'dashboard')
            else:
                messages.error(request, 'Your account is disabled.')
        else:
            messages.error(request, 'Invalid username or password.')
    
    context = {
        'next': request.GET.get('next', ''),
    }
    
    return render(request, 'auth/login.html', context)

Custom Logout Views

# Custom logout view implementations
from django.contrib.auth.views import LogoutView
from django.contrib.auth import logout
from django.shortcuts import render, redirect

class CustomLogoutView(LogoutView):
    """Enhanced logout view with additional features"""
    
    template_name = 'auth/logout.html'
    
    def dispatch(self, request, *args, **kwargs):
        """Handle logout process"""
        
        if request.user.is_authenticated:
            # Log logout
            import logging
            logger = logging.getLogger('auth')
            logger.info(f"User {request.user.username} logged out")
            
            # Store user info before logout
            user_info = {
                'username': request.user.username,
                'full_name': request.user.get_full_name(),
            }
            
            # Clear custom session data
            session_keys_to_clear = [
                'user_preferences', 'shopping_cart', 'temp_data'
            ]
            
            for key in session_keys_to_clear:
                request.session.pop(key, None)
            
            # Add logout message
            messages.info(
                request, 
                f"You have been logged out, {user_info['full_name'] or user_info['username']}."
            )
        
        return super().dispatch(request, *args, **kwargs)
    
    def get_next_page(self):
        """Determine where to redirect after logout"""
        
        next_page = super().get_next_page()
        
        if next_page:
            return next_page
        
        # Custom logout redirect logic
        return reverse_lazy('home')

class AjaxLogoutView(LogoutView):
    """Logout view that supports AJAX requests"""
    
    def dispatch(self, request, *args, **kwargs):
        """Handle AJAX logout"""
        
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            if request.user.is_authenticated:
                username = request.user.username
                logout(request)
                
                return JsonResponse({
                    'success': True,
                    'message': f'Goodbye, {username}!',
                    'redirect_url': self.get_next_page()
                })
            else:
                return JsonResponse({
                    'success': False,
                    'message': 'Not logged in'
                })
        
        return super().dispatch(request, *args, **kwargs)

# Function-based logout view
def custom_logout_view(request):
    """Custom function-based logout view"""
    
    if request.user.is_authenticated:
        username = request.user.username
        
        # Clear specific session data
        request.session.pop('user_preferences', None)
        
        # Log out user
        logout(request)
        
        messages.success(request, f'You have been logged out, {username}.')
    
    return redirect('home')

Password Change Views

# Custom password change views
from django.contrib.auth.views import PasswordChangeView, PasswordChangeDoneView
from django.contrib.auth.forms import PasswordChangeForm
from django.contrib.auth.decorators import login_required

class CustomPasswordChangeView(PasswordChangeView):
    """Enhanced password change view"""
    
    template_name = 'auth/password_change.html'
    success_url = reverse_lazy('password_change_done')
    
    def form_valid(self, form):
        """Handle successful password change"""
        
        response = super().form_valid(form)
        
        user = self.request.user
        
        # Log password change
        import logging
        logger = logging.getLogger('auth')
        logger.info(f"Password changed for user: {user.username}")
        
        # Store password change timestamp
        if hasattr(user, 'profile'):
            user.profile.password_changed_at = timezone.now()
            user.profile.save()
        
        # Invalidate all other sessions
        from django.contrib.sessions.models import Session
        
        current_session_key = self.request.session.session_key
        
        # Get all user sessions
        user_sessions = []
        for session in Session.objects.all():
            try:
                session_data = session.get_decoded()
                if session_data.get('_auth_user_id') == str(user.id):
                    if session.session_key != current_session_key:
                        user_sessions.append(session)
            except:
                continue
        
        # Delete other sessions
        for session in user_sessions:
            session.delete()
        
        messages.success(
            self.request,
            'Your password has been changed successfully. '
            'All other sessions have been logged out for security.'
        )
        
        return response
    
    def get_context_data(self, **kwargs):
        """Add password strength requirements to context"""
        
        context = super().get_context_data(**kwargs)
        
        context.update({
            'password_requirements': [
                'At least 12 characters long',
                'Contains uppercase and lowercase letters',
                'Contains at least one number',
                'Contains at least one special character',
                'Not similar to your personal information',
                'Not a commonly used password'
            ]
        })
        
        return context

class CustomPasswordChangeDoneView(PasswordChangeDoneView):
    """Custom password change success view"""
    
    template_name = 'auth/password_change_done.html'
    
    def get_context_data(self, **kwargs):
        """Add additional context"""
        
        context = super().get_context_data(**kwargs)
        
        context.update({
            'next_steps': [
                'Update your password in any saved browsers',
                'Update your password in mobile apps',
                'Consider enabling two-factor authentication'
            ]
        })
        
        return context

# Function-based password change view
@login_required
def custom_password_change_view(request):
    """Custom function-based password change view"""
    
    if request.method == 'POST':
        form = PasswordChangeForm(request.user, request.POST)
        
        if form.is_valid():
            user = form.save()
            
            # Update session to prevent logout
            from django.contrib.auth import update_session_auth_hash
            update_session_auth_hash(request, user)
            
            messages.success(request, 'Your password has been changed successfully!')
            return redirect('password_change_done')
    else:
        form = PasswordChangeForm(request.user)
    
    return render(request, 'auth/password_change.html', {'form': form})

Password Reset Views

# Custom password reset views
from django.contrib.auth.views import (
    PasswordResetView, PasswordResetDoneView,
    PasswordResetConfirmView, PasswordResetCompleteView
)
from django.contrib.auth.forms import PasswordResetForm, SetPasswordForm
from django.core.mail import send_mail
from django.template.loader import render_to_string

class CustomPasswordResetView(PasswordResetView):
    """Enhanced password reset view"""
    
    template_name = 'auth/password_reset.html'
    email_template_name = 'auth/password_reset_email.html'
    subject_template_name = 'auth/password_reset_subject.txt'
    success_url = reverse_lazy('password_reset_done')
    
    def form_valid(self, form):
        """Handle password reset request"""
        
        email = form.cleaned_data['email']
        
        # Rate limiting
        from django.core.cache import cache
        
        cache_key = f"password_reset_{email}"
        recent_requests = cache.get(cache_key, 0)
        
        if recent_requests >= 3:
            messages.error(
                self.request,
                "Too many password reset requests. Please try again later."
            )
            return redirect('password_reset')
        
        # Increment request count
        cache.set(cache_key, recent_requests + 1, 3600)  # 1 hour
        
        # Log password reset request
        import logging
        logger = logging.getLogger('auth')
        logger.info(f"Password reset requested for email: {email}")
        
        return super().form_valid(form)
    
    def send_mail(self, subject_template_name, email_template_name,
                  context, from_email, to_email, html_email_template_name=None):
        """Send password reset email with enhanced template"""
        
        # Add additional context
        context.update({
            'site_name': 'Your Site Name',
            'support_email': 'support@yoursite.com',
            'security_tips': [
                'Never share your password with anyone',
                'Use a unique password for this account',
                'Consider enabling two-factor authentication'
            ]
        })
        
        return super().send_mail(
            subject_template_name, email_template_name, context,
            from_email, to_email, html_email_template_name
        )

class CustomPasswordResetConfirmView(PasswordResetConfirmView):
    """Enhanced password reset confirmation view"""
    
    template_name = 'auth/password_reset_confirm.html'
    success_url = reverse_lazy('password_reset_complete')
    
    def form_valid(self, form):
        """Handle successful password reset"""
        
        response = super().form_valid(form)
        
        user = form.user
        
        # Log successful password reset
        import logging
        logger = logging.getLogger('auth')
        logger.info(f"Password reset completed for user: {user.username}")
        
        # Invalidate all user sessions
        from django.contrib.sessions.models import Session
        
        for session in Session.objects.all():
            try:
                session_data = session.get_decoded()
                if session_data.get('_auth_user_id') == str(user.id):
                    session.delete()
            except:
                continue
        
        # Send confirmation email
        send_mail(
            'Password Reset Successful',
            f'Your password has been reset successfully for {user.username}.',
            settings.DEFAULT_FROM_EMAIL,
            [user.email],
            fail_silently=True,
        )
        
        messages.success(
            self.request,
            'Your password has been reset successfully. '
            'Please log in with your new password.'
        )
        
        return response

# Two-factor authentication integration
class TwoFactorLoginView(LoginView):
    """Login view with two-factor authentication"""
    
    template_name = 'auth/2fa_login.html'
    
    def form_valid(self, form):
        """Handle login with 2FA check"""
        
        user = form.get_user()
        
        # Check if user has 2FA enabled
        if hasattr(user, 'profile') and user.profile.two_factor_enabled:
            # Store user in session temporarily
            self.request.session['2fa_user_id'] = user.id
            self.request.session['2fa_timestamp'] = timezone.now().isoformat()
            
            # Redirect to 2FA verification
            return redirect('2fa_verify')
        
        # Normal login process
        return super().form_valid(form)

def two_factor_verify_view(request):
    """Verify two-factor authentication token"""
    
    if request.method == 'POST':
        token = request.POST.get('token')
        user_id = request.session.get('2fa_user_id')
        
        if not user_id:
            messages.error(request, 'Invalid session. Please log in again.')
            return redirect('login')
        
        try:
            user = User.objects.get(id=user_id)
            
            # Verify TOTP token (example with pyotp)
            import pyotp
            
            if hasattr(user, 'profile') and user.profile.totp_secret:
                totp = pyotp.TOTP(user.profile.totp_secret)
                
                if totp.verify(token, valid_window=1):
                    # Complete login
                    login(request, user)
                    
                    # Clean up session
                    del request.session['2fa_user_id']
                    del request.session['2fa_timestamp']
                    
                    messages.success(request, 'Login successful!')
                    return redirect('dashboard')
                else:
                    messages.error(request, 'Invalid verification code.')
            else:
                messages.error(request, 'Two-factor authentication not properly configured.')
        
        except User.DoesNotExist:
            messages.error(request, 'Invalid session. Please log in again.')
            return redirect('login')
    
    return render(request, 'auth/2fa_verify.html')

Django's authentication views provide a solid foundation for implementing secure authentication workflows. By customizing these views, you can add enhanced security features, improved user experience, and integration with additional authentication methods while maintaining the robustness of Django's built-in security measures.

Registration Views

User Registration Implementation

# Custom user registration views
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import login
from django.views.generic import CreateView
from django.urls import reverse_lazy

class CustomUserCreationForm(UserCreationForm):
    """Enhanced user creation form"""
    
    email = forms.EmailField(required=True)
    first_name = forms.CharField(max_length=30, required=True)
    last_name = forms.CharField(max_length=30, required=True)
    terms_accepted = forms.BooleanField(
        required=True,
        label="I accept the Terms of Service and Privacy Policy"
    )
    
    class Meta:
        model = User
        fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2')
    
    def clean_email(self):
        """Validate email uniqueness"""
        email = self.cleaned_data['email']
        
        if User.objects.filter(email=email).exists():
            raise forms.ValidationError("A user with this email already exists.")
        
        return email
    
    def clean_username(self):
        """Additional username validation"""
        username = self.cleaned_data['username']
        
        # Check for reserved usernames
        reserved_usernames = ['admin', 'root', 'administrator', 'moderator']
        
        if username.lower() in reserved_usernames:
            raise forms.ValidationError("This username is reserved.")
        
        return username
    
    def save(self, commit=True):
        """Save user with additional fields"""
        user = super().save(commit=False)
        user.email = self.cleaned_data['email']
        user.first_name = self.cleaned_data['first_name']
        user.last_name = self.cleaned_data['last_name']
        
        if commit:
            user.save()
        
        return user

class RegistrationView(CreateView):
    """User registration view"""
    
    form_class = CustomUserCreationForm
    template_name = 'auth/register.html'
    success_url = reverse_lazy('registration_complete')
    
    def dispatch(self, request, *args, **kwargs):
        """Redirect authenticated users"""
        if request.user.is_authenticated:
            return redirect('dashboard')
        
        return super().dispatch(request, *args, **kwargs)
    
    def form_valid(self, form):
        """Handle successful registration"""
        
        response = super().form_valid(form)
        
        user = self.object
        
        # Log registration
        import logging
        logger = logging.getLogger('auth')
        logger.info(f"New user registered: {user.username} ({user.email})")
        
        # Send welcome email
        self.send_welcome_email(user)
        
        # Auto-login after registration
        login(self.request, user)
        
        messages.success(
            self.request,
            f'Welcome to our site, {user.get_full_name() or user.username}! '
            'Your account has been created successfully.'
        )
        
        return response
    
    def send_welcome_email(self, user):
        """Send welcome email to new user"""
        
        subject = 'Welcome to Our Site!'
        message = render_to_string('auth/welcome_email.html', {
            'user': user,
            'site_name': 'Your Site Name',
        })
        
        send_mail(
            subject,
            message,
            settings.DEFAULT_FROM_EMAIL,
            [user.email],
            fail_silently=True,
        )

class EmailVerificationRequiredRegistrationView(CreateView):
    """Registration view that requires email verification"""
    
    form_class = CustomUserCreationForm
    template_name = 'auth/register.html'
    success_url = reverse_lazy('registration_email_sent')
    
    def form_valid(self, form):
        """Handle registration with email verification"""
        
        response = super().form_valid(form)
        
        user = self.object
        
        # Set user as inactive until email verification
        user.is_active = False
        user.save()
        
        # Send verification email
        self.send_verification_email(user)
        
        messages.info(
            self.request,
            'Please check your email and click the verification link to activate your account.'
        )
        
        return response
    
    def send_verification_email(self, user):
        """Send email verification link"""
        
        from django.contrib.auth.tokens import default_token_generator
        from django.utils.http import urlsafe_base64_encode
        from django.utils.encoding import force_bytes
        
        # Generate verification token
        token = default_token_generator.make_token(user)
        uid = urlsafe_base64_encode(force_bytes(user.pk))
        
        # Create verification URL
        verification_url = self.request.build_absolute_uri(
            reverse('email_verify', kwargs={'uidb64': uid, 'token': token})
        )
        
        # Send email
        subject = 'Verify Your Email Address'
        message = render_to_string('auth/verification_email.html', {
            'user': user,
            'verification_url': verification_url,
            'site_name': 'Your Site Name',
        })
        
        send_mail(
            subject,
            message,
            settings.DEFAULT_FROM_EMAIL,
            [user.email],
            fail_silently=False,
        )

def email_verify_view(request, uidb64, token):
    """Verify email address"""
    
    try:
        uid = force_str(urlsafe_base64_decode(uidb64))
        user = User.objects.get(pk=uid)
    except (TypeError, ValueError, OverflowError, User.DoesNotExist):
        user = None
    
    if user is not None and default_token_generator.check_token(user, token):
        # Activate user account
        user.is_active = True
        user.save()
        
        # Log in user
        login(request, user)
        
        messages.success(
            request,
            'Your email has been verified successfully! Welcome to our site.'
        )
        
        return redirect('dashboard')
    else:
        messages.error(
            request,
            'The verification link is invalid or has expired.'
        )
        
        return redirect('register')

# Function-based registration view
def register_view(request):
    """Function-based registration view"""
    
    if request.user.is_authenticated:
        return redirect('dashboard')
    
    if request.method == 'POST':
        form = CustomUserCreationForm(request.POST)
        
        if form.is_valid():
            user = form.save()
            
            # Log registration
            import logging
            logger = logging.getLogger('auth')
            logger.info(f"New user registered: {user.username}")
            
            # Auto-login
            login(request, user)
            
            messages.success(
                request,
                f'Welcome, {user.get_full_name() or user.username}! '
                'Your account has been created.'
            )
            
            return redirect('dashboard')
    else:
        form = CustomUserCreationForm()
    
    return render(request, 'auth/register.html', {'form': form})

Profile Management Views

User Profile Views

# User profile management views
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin

class UserProfileForm(forms.ModelForm):
    """Form for editing user profile"""
    
    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'email']
    
    def clean_email(self):
        """Validate email uniqueness"""
        email = self.cleaned_data['email']
        
        # Exclude current user from uniqueness check
        if User.objects.filter(email=email).exclude(pk=self.instance.pk).exists():
            raise forms.ValidationError("A user with this email already exists.")
        
        return email

class UserProfileView(LoginRequiredMixin, UpdateView):
    """User profile editing view"""
    
    model = User
    form_class = UserProfileForm
    template_name = 'auth/profile.html'
    success_url = reverse_lazy('profile')
    
    def get_object(self):
        """Return current user as object"""
        return self.request.user
    
    def form_valid(self, form):
        """Handle successful profile update"""
        
        response = super().form_valid(form)
        
        messages.success(
            self.request,
            'Your profile has been updated successfully.'
        )
        
        return response

class UserProfileDetailView(LoginRequiredMixin, DetailView):
    """View user profile details"""
    
    model = User
    template_name = 'auth/profile_detail.html'
    context_object_name = 'profile_user'
    
    def get_object(self):
        """Return current user as object"""
        return self.request.user
    
    def get_context_data(self, **kwargs):
        """Add additional context"""
        
        context = super().get_context_data(**kwargs)
        
        user = self.object
        
        context.update({
            'user_stats': {
                'date_joined': user.date_joined,
                'last_login': user.last_login,
                'is_staff': user.is_staff,
                'groups': user.groups.all(),
            },
            'recent_activity': self.get_recent_activity(user),
        })
        
        return context
    
    def get_recent_activity(self, user):
        """Get user's recent activity"""
        
        # This would depend on your activity tracking system
        # Example implementation:
        
        activity = []
        
        # Recent posts
        if hasattr(user, 'posts'):
            recent_posts = user.posts.order_by('-created_at')[:5]
            for post in recent_posts:
                activity.append({
                    'type': 'post_created',
                    'description': f'Created post: {post.title}',
                    'timestamp': post.created_at,
                })
        
        # Recent comments
        if hasattr(user, 'comments'):
            recent_comments = user.comments.order_by('-created_at')[:5]
            for comment in recent_comments:
                activity.append({
                    'type': 'comment_created',
                    'description': f'Commented on: {comment.post.title}',
                    'timestamp': comment.created_at,
                })
        
        # Sort by timestamp
        activity.sort(key=lambda x: x['timestamp'], reverse=True)
        
        return activity[:10]  # Return latest 10 activities

@login_required
def profile_view(request):
    """Function-based profile view"""
    
    if request.method == 'POST':
        form = UserProfileForm(request.POST, instance=request.user)
        
        if form.is_valid():
            form.save()
            messages.success(request, 'Profile updated successfully.')
            return redirect('profile')
    else:
        form = UserProfileForm(instance=request.user)
    
    context = {
        'form': form,
        'user': request.user,
    }
    
    return render(request, 'auth/profile.html', context)

Account Management Views

Account Settings and Security

# Account management and security views
class AccountSettingsView(LoginRequiredMixin, TemplateView):
    """Account settings dashboard"""
    
    template_name = 'auth/account_settings.html'
    
    def get_context_data(self, **kwargs):
        """Add account information to context"""
        
        context = super().get_context_data(**kwargs)
        
        user = self.request.user
        
        context.update({
            'user': user,
            'security_info': {
                'password_last_changed': getattr(user, 'password_changed_at', None),
                'two_factor_enabled': getattr(user.profile, 'two_factor_enabled', False) if hasattr(user, 'profile') else False,
                'active_sessions': self.get_active_sessions(user),
            },
            'privacy_settings': self.get_privacy_settings(user),
            'notification_settings': self.get_notification_settings(user),
        })
        
        return context
    
    def get_active_sessions(self, user):
        """Get user's active sessions"""
        
        from django.contrib.sessions.models import Session
        
        active_sessions = []
        current_session_key = self.request.session.session_key
        
        for session in Session.objects.filter(expire_date__gt=timezone.now()):
            try:
                session_data = session.get_decoded()
                session_user_id = session_data.get('_auth_user_id')
                
                if session_user_id and int(session_user_id) == user.id:
                    active_sessions.append({
                        'session_key': session.session_key,
                        'is_current': session.session_key == current_session_key,
                        'expire_date': session.expire_date,
                        'ip_address': session_data.get('ip_address', 'Unknown'),
                        'user_agent': session_data.get('user_agent', 'Unknown')[:50],
                    })
            except:
                continue
        
        return active_sessions
    
    def get_privacy_settings(self, user):
        """Get user's privacy settings"""
        
        # This would depend on your privacy settings implementation
        if hasattr(user, 'profile'):
            return {
                'profile_public': getattr(user.profile, 'profile_public', True),
                'email_public': getattr(user.profile, 'email_public', False),
                'activity_public': getattr(user.profile, 'activity_public', True),
            }
        
        return {}
    
    def get_notification_settings(self, user):
        """Get user's notification settings"""
        
        # This would depend on your notification system
        if hasattr(user, 'profile'):
            return {
                'email_notifications': getattr(user.profile, 'email_notifications', True),
                'push_notifications': getattr(user.profile, 'push_notifications', False),
                'marketing_emails': getattr(user.profile, 'marketing_emails', False),
            }
        
        return {}

class TerminateSessionView(LoginRequiredMixin, View):
    """Terminate specific user session"""
    
    def post(self, request, *args, **kwargs):
        """Terminate session"""
        
        session_key = request.POST.get('session_key')
        
        if session_key and session_key != request.session.session_key:
            try:
                from django.contrib.sessions.models import Session
                
                session = Session.objects.get(session_key=session_key)
                
                # Verify session belongs to current user
                session_data = session.get_decoded()
                session_user_id = session_data.get('_auth_user_id')
                
                if session_user_id and int(session_user_id) == request.user.id:
                    session.delete()
                    messages.success(request, 'Session terminated successfully.')
                else:
                    messages.error(request, 'Invalid session.')
            
            except Session.DoesNotExist:
                messages.error(request, 'Session not found.')
        else:
            messages.error(request, 'Cannot terminate current session.')
        
        return redirect('account_settings')

class DeleteAccountView(LoginRequiredMixin, TemplateView):
    """Account deletion view"""
    
    template_name = 'auth/delete_account.html'
    
    def post(self, request, *args, **kwargs):
        """Handle account deletion"""
        
        password = request.POST.get('password')
        confirmation = request.POST.get('confirmation')
        
        # Verify password
        if not request.user.check_password(password):
            messages.error(request, 'Incorrect password.')
            return self.get(request, *args, **kwargs)
        
        # Verify confirmation
        if confirmation != 'DELETE':
            messages.error(request, 'Please type DELETE to confirm.')
            return self.get(request, *args, **kwargs)
        
        # Log account deletion
        import logging
        logger = logging.getLogger('auth')
        logger.info(f"Account deleted: {request.user.username}")
        
        # Store user info before deletion
        username = request.user.username
        
        # Delete user account
        request.user.delete()
        
        # Log out and redirect
        logout(request)
        
        messages.success(
            request,
            f'Account {username} has been deleted successfully.'
        )
        
        return redirect('home')

# Two-factor authentication setup
class TwoFactorSetupView(LoginRequiredMixin, TemplateView):
    """Two-factor authentication setup"""
    
    template_name = 'auth/2fa_setup.html'
    
    def get_context_data(self, **kwargs):
        """Add 2FA setup context"""
        
        context = super().get_context_data(**kwargs)
        
        user = self.request.user
        
        # Generate TOTP secret if not exists
        if not hasattr(user, 'profile') or not user.profile.totp_secret:
            import pyotp
            secret = pyotp.random_base32()
            
            if hasattr(user, 'profile'):
                user.profile.totp_secret = secret
                user.profile.save()
        else:
            secret = user.profile.totp_secret
        
        # Generate QR code
        import pyotp
        import qrcode
        from io import BytesIO
        import base64
        
        totp_uri = pyotp.totp.TOTP(secret).provisioning_uri(
            name=user.email,
            issuer_name="Your Site Name"
        )
        
        qr = qrcode.QRCode(version=1, box_size=10, border=5)
        qr.add_data(totp_uri)
        qr.make(fit=True)
        
        img = qr.make_image(fill_color="black", back_color="white")
        buffer = BytesIO()
        img.save(buffer, format='PNG')
        buffer.seek(0)
        
        qr_code_data = base64.b64encode(buffer.getvalue()).decode()
        
        context.update({
            'secret': secret,
            'qr_code': qr_code_data,
            'totp_uri': totp_uri,
        })
        
        return context
    
    def post(self, request, *args, **kwargs):
        """Verify and enable 2FA"""
        
        token = request.POST.get('token')
        
        if hasattr(request.user, 'profile') and request.user.profile.totp_secret:
            import pyotp
            
            totp = pyotp.TOTP(request.user.profile.totp_secret)
            
            if totp.verify(token, valid_window=1):
                # Enable 2FA
                request.user.profile.two_factor_enabled = True
                request.user.profile.save()
                
                messages.success(
                    request,
                    'Two-factor authentication has been enabled successfully.'
                )
                
                return redirect('account_settings')
            else:
                messages.error(request, 'Invalid verification code.')
        else:
            messages.error(request, 'Two-factor authentication not properly configured.')
        
        return self.get(request, *args, **kwargs)

Authentication views form the user-facing interface of your authentication system. By implementing comprehensive, secure, and user-friendly authentication views, you provide users with a smooth experience while maintaining strong security standards throughout the authentication process.