# 🔑 Authentication mit Django REST Framework (DRF) ## Inhaltsverzeichnis 1. [Einleitung](#einleitung) 2. [Grundlagen](#grundlagen) 3. [Schritt-für-Schritt-Aufbau](#schritt-für-schritt-aufbau) - [1. App erstellen & DRF Paket installieren sowie settings anpassen](#1-app-erstellen--drf-paket-installieren-sowie-settings-anpassen) - [2. Migrationen ausführen](#2-migrationen-ausführen) - [3. Manuelle Token-Erzeugung im Admin](#3-manuelle-token-erzeugung-im-admin) - [4. Testen mit Postman](#4-testen-mit-postman) 4. [Automatische Registrierung und Login Möglichkeiten](#automatische-registrierung-und-login-möglichkeiten) - [1. Registration-Serializer mit Passwort-Bestätigung](#1-registration-serializer-mit-passwort-bestätigung) - [2. Schneller Login-Endpoint mit `obtain_auth_token`](#2-schneller-login-endpoint-mit-obtain_auth_token) - [3. CustomLoginView für erweiterte Antworten](#3-customloginview-für-erweiterte-antworten) - [4. Optional: Automatische Token-Erzeugung via Signal bei Erstellung eines Users](#4-optional-automatische-token-erzeugung-via-signal-bei-erstellung-eines-users) - [5. Logout View](#5-logout-view) 5. [Best Practices](#best-practices) ## Einleitung Die Token-basierte Authentifizierung ist eine Methode, bei der Benutzer nach erfolgreicher Anmeldung ein einmaliges Token erhalten, das sie für alle nachfolgenden API-Anfragen im HTTP-Header `Authorization` mitsenden können. Sie ermöglicht eine zustandslose, skalierbare und sichere Kommunikation zwischen Client und Server, besonders geeignet für mobile und Single-Page-Applications. ## Grundlagen ### DRF-Paket und Modelle Django REST Framework stellt mit `rest_framework.authtoken` das `Token`-Modell bereit, das von der Authentifizierungsklasse `TokenAuthentication` genutzt wird. > Doku: https://www.django-rest-framework.org/api-guide/authentication/ --- ## Schritt-für-Schritt-Aufbau ### 1. App erstellen & DRF Paket installieren sowie settings anpassen ```python # settings.py INSTALLED_APPS = [ ..., 'rest_framework', 'rest_framework.authtoken', ] REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.TokenAuthentication', ], } ``` ### 2. Migrationen ausführen Dies erzeugt die Tabelle `authtoken_token` für die Speicherung der Tokens. ### 3. Manuelle Token-Erzeugung im Admin Im Django-Admin findest Du unter **Auth Token > Tokens** die Möglichkeit, für jeden User manuell ein Token anzulegen. >Mit der Token-Authentifizierung bekommt jeder Benutzer einen eindeutigen Token. Anstatt bei jeder Anfrage seine Login-Daten (Benutzername und Passwort) zu senden, wird immer der Token verwendet und mitgeschickt, um den Benutzer zu authentifizieren und zu autorisieren. Dies erhöht die Sicherheit und vereinfacht die Authentifizierung, da der Benutzer nur den Token übermitteln muss, um Zugriff auf die geschützten Ressourcen zu erhalten. ### 4. Testen mit Postman - Öffne Postman, setze bei **Headers** den Key `Authorization` mit dem Wert ``` Token <dein-token> ``` - Sende eine API-Anfrage an geschützte Endpunkte (Permission: isAuthenticated). Nur mit gültigem Token erhältst Du Zugriff. ## Automatische Registrierung und Login möglichkeiten ### 1. Registration-Serializer mit Passwort-Bestätigung ```python # user_auth_app/serializers.py from rest_framework import serializers from django.contrib.auth.models import User class RegistrationSerializer(serializers.ModelSerializer): repeated_password = serializers.CharField(write_only=True) class Meta: model = User fields = ['username', 'email', 'password', 'repeated_password'] extra_kwargs = { 'password': { 'write_only': True } } def save(self): pw = self.validated_data['password'] repeated_pw = self.validated_data['repeated_password'] user_email = self.validated_data['email'] if pw != repeated_pw: raise serializers.ValidationError({'error': 'Passwords do not match!'}) if User.objects.filter(email=user_email).exists(): raise serializers.ValidationError({'error': 'Email already exists!'}) if User.objects.filter(username=self.validated_data['username']).exists(): raise serializers.ValidationError({'error': 'Username already exists!'}) account = User(email=self.validated_data['email'], username=self.validated_data['username']) account.set_password(pw) account.save() return account ``` ### 2. Schneller Login-Endpoint mit `obtain_auth_token` ```python # user_auth_app/urls.py from rest_framework.authtoken.views import obtain_auth_token urlpatterns = [ path('login/', obtain_auth_token, name='login'), ] ``` Hier sendet der User `username` und `password` und erhält bei Erfolg sein Token zurück. >Doku: https://www.django-rest-framework.org/api-guide/authentication/#by-exposing-an-api-endpoint ### 3. CustomLoginView für erweiterte Antworten ```python # user_auth_app/views.py from rest_framework.authtoken.views import ObtainAuthToken from rest_framework.authtoken.models import Token from rest_framework.permissions import AllowAny from rest_framework.response import Response class CustomLoginView(ObtainAuthToken): permission_classes = [AllowAny] def post(self, request, *args, **kwargs): serializer = self.serializer_class(data=request.data, context={'request': request}) serializer.is_valid(raise_exception=True) user = serializer.validated_data['user'] token, created = Token.objects.get_or_create(user=user) return Response({ 'token': token.key, 'username': user.username, 'email': user.email, }) ``` Und in `urls.py`: ```python path('login/', CustomLoginView.as_view(), name='custom-login') ``` So erhältst Du zusätzlich Benutzername und E-Mail im Response >Doku: https://www.django-rest-framework.org/api-guide/authentication/#by-exposing-an-api-endpoint > --- ### 4. Optional: Automatische Token-Erzeugung via Signal bei erstellung eines Users ```python # user_auth_app/signals.py from django.conf import settings from django.db.models.signals import post_save from django.dispatch import receiver from rest_framework.authtoken.models import Token @receiver(post_save, sender=settings.AUTH_USER_MODEL) def create_auth_token(sender, instance=None, created=False, **kwargs): if created: Token.objects.create(user=instance) ``` Und verknüpfst die Datei in `apps.py` oder `__init__.py` Deiner App. >Doku: https://www.django-rest-framework.org/api-guide/authentication/#by-using-signals ### 5. Logout View ```python class LogoutView(APIView): authentication_classes = [TokenAuthentication] permission_classes = [IsAuthenticated] def post(self, request): # Löscht das Token des aktuell authentifizierten Benutzers request.user.auth_token.delete() return Response(status=200) ``` --- ## Best Practices - **HTTPS**: Verwende in Produktion immer HTTPS, damit Tokens nicht abgefangen werden können.