JWT Token Authentifizierung

Um JWT Token zu nutzen installieren wir zuerst das Paket Simple JWT.

SIMPLE JWT installieren

Wir legen in der requirements.in fest:

# andere Apps
djangorestframework-simplejwt

und installieren sie:

(eventenv)  pip-compile requirements.in
(eventenv)  pip-sync requirements.txt requirements-dev.txt

Mehr zu Simple JWT in der Doku: https://django-rest-framework-simplejwt.readthedocs.io/en/latest

Settings

in den Settings müssen wir die Authentication-Classes angeben:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
}

Urls

In den Projekt-URLs unter event_manager/event_manager/urls.py legen wir die URls fest

from django.urls import path
from rest_framework_simplejwt import views as jwt_views

urlpatterns = [
    # andere URLs
    path('api/jwt/token/', jwt_views.TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/jwt/token/refresh/', jwt_views.TokenRefreshView.as_view(), name='token_refresh'),
]

Pages App

in der Pages App legen wir ein neues Verzeichnis unter event_manager/pages/api an und tragen in die Datei views.py folgende Beispiel-View

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated


class PagesView(APIView):
    permission_classes = (IsAuthenticated,)

    def get(self, request):
        content = {"message": "Hello, World!"}
        return Response(content)

Unter event_manager/pages/api/urls.py tragen wir die entsprechenden Urls ein:

from django.urls import path
from . import views

urlpatterns = [
    path('hello/', views.PagesView.as_view(), name='hello'),
]

Obtain Token

Um den Token zu erhalten, müssen wir den Endpunkt für obtain_token aufrufen:

curl -X POST -d "username=admin&password=GEHEIM" 127.0.0.1:8000/api/jwt/token/

Der Rückgabwert besteht aus einem access und einem refresh - Token.

gekürzte Ausgabe:

{"refresh":"8BXUOongUbaAnnDFESMEMsw",
"access":"ji9y0MXiu1MfoqMv7ZeBTkrXUAxWiHBouKmFYoh97E"}

Danach werden sowohl der access-Token als auch das refresh-Token auf der Client-Seite gespeichert, normalerweise im localStorage des Browsers. Der access-token ist fünf Minuten gültig, danach muss er erneuert werden.

Um die Resource jetzt aufzufen muss der acces-token mitgesendet werden:

curl -X GET -H "Authorization: Bearer <ACCESS TOKEN>"  http://127.0.0.1:8000/pages/api/hello/
{"message":"Hello, World!"}

REFRESH TOKEN

Um einen neuen Token zu erhalten, kann man den Refresh URL nutzen. Als Ergebnis erhält man einen neuen Access Token:

curl -X POST -d "<REFRESH TOKEN>" 127.0.0.1:8000/api/jwt/token/refresh/

{"access":<NEUER ACCESS TOKEN>}

Das Refresh-Token ist für die nächsten 24 Stunden gültig. Wenn es schließlich auch abläuft, muss der Benutzer eine vollständige Authentifizierung mit seinem Benutzernamen und Passwort durchführen, um einen neuen Satz von Zugangstoken und Refresh-Token zu erhalten.

Auf den ersten Blick mag das Aktualisierungs-Token sinnlos erscheinen, tatsächlich ist es aber notwendig, um sicherzustellen, dass der Benutzer noch über die richtigen Berechtigungen verfügt. Wenn Ihr Zugangstoken eine lange Ablaufzeit hat, kann es länger dauern, die mit dem Token verbundenen Informationen zu aktualisieren. Das liegt daran, dass die Authentifizierungsprüfung mit kryptografischen Mitteln erfolgt, anstatt die Datenbank abzufragen und die Daten zu verifizieren. Einige Informationen werden also gewissermaßen zwischengespeichert.

Es gibt auch einen Sicherheitsaspekt in dem Sinne, dass das Refresh-Token nur in den POST-Daten unterwegs ist. Und das Zugriffstoken wird über einen HTTP-Header gesendet, der auf dem Weg protokolliert werden kann. Dies bietet also auch ein kurzes Zeitfenster, falls Ihr Zugriffstoken kompromittiert werden sollte.

Ein Refresh-Token erhält ein Zugriffstoken, ohne dass der Benutzer seine Anmeldedaten eingeben muss, um die Sitzung des Benutzers zu verlängern. Dies bietet eine nahtlose Benutzererfahrung und verbessert die Sicherheit, da der Benutzer seine Anmeldeinformationen weniger oft eingeben muss.

Swagger UI

Die API - Endpunkte wurden alle ebenfalls in der SWAGGER Ui gesammelt und können ausprobiert werden.

in das Feld „Authenticate“ muss der access-Token kopiert werden:

API Endpunkte für User Authentication

Die Endpunkte, die Django per Default für Login, Registierung und so weiter anbietet, eignen sich nicht für das Django Rest Framework.

Hier bietet sich die App „Djoser“ an: https://djoser.readthedocs.io/en/latest/base_endpoints.html

REST implementation of Django authentication system. djoser library provides a set of Django Rest Framework views to handle basic actions such as registration, login, logout, password reset and account activation. It works with custom user model.

Instead of reusing Django code (e.g. PasswordResetForm), we reimplemented few things to fit

better into Single Page App architecture.

gutes Tutorial: https://fathinah.medium.com/calling-rest-api-with-jwt-authentication-in-django-b1c48b8018ed

React Anwendung mit Djoser

https://www.section.io/engineering-education/social-authentication-with-djoser-in-react-applications/