Dans l'écosystème de Django REST Framework, la bibliothèque SimpleJWT fournit la classe AccessToken pour représenter la composante d'accès d'un JSON Web Token (JWT). Ce jeton est fondamental pour sécuriser les points de terminaison d'une API en transportant des informations d'authentificaiton, des permissions et une durée de validité.
La classe AccessToken offre trois fonctionnalités principales :
- Génération : Elle permet d'émettre de nouveaux jetons via des méthodes comme
for_user(pour un utilisateur spécifique) ou d'instancier un objet à partir d'une chaîne existante. - Décodage : La méthode
decodetransforme une chaîne JWT en objetAccessToken, facilitant l'extraction des données de la charge utile (payload). - Validation : Des méthodes intégrées telles que
verifyetverify_expgarantissent l'intégrité du jeton et vérifient qu'il n'a pas expiré ou été altéré.
Création de jetons avec for_user
La méthode de classe AccessToken.for_user est conçue pour générer un jeton d'accès lié à une instance du modèle utilisateur de Django. Elle encapsule les informations d'identification et les métadonnées de session dans la charge utile du JWT.
Voici une implémentation modifiée illustrant son utilisation :
from django.contrib.auth import get_user_model
from rest_framework_simplejwt.tokens import AccessToken
UserModel = get_user_model()
# Récupération de l'utilisateur cible
target_account = UserModel.objects.get(email='admin@example.com')
# Instanciation du jeton d'accès
token_instance = AccessToken.for_user(target_account)
# Sérialisation en chaîne de caractères pour la transmission
encoded_token = str(token_instance)
Dans ce scénario, token_instance est un objet Python riche qui peut être manipulé avant d'être converti en chaîne via la fonction native str().
Génération rapide avec get_token
Pour les cas où la manipulation de l'objet token n'est pas nécessaire, SimpleJWT propose la fonction utilitaire get_token. Cette fonction prend directement une instance utilisateur et retourne la chaîne JWT encodée, contournant ainsi l'étape de conversion manuelle.
Exemple d'implémentation :
from django.contrib.auth import get_user_model
from rest_framework_simplejwt.tokens import get_token
UserModel = get_user_model()
# Identification de l'utilisateur
target_account = UserModel.objects.get(email='admin@example.com')
# Obtention directe de la chaîne JWT
raw_jwt_string = get_token(target_account)
Ici, raw_jwt_string est immédiatement prêt à être envoyé au client, ce qui rend le code plus concis lorsque seule la valeur textuelle du jeton est requise.
Intégration avec les Sérialiseurs
Lors de l'authentification via des identifiants bruts, il est courant de combiner la validation des données avec la génération du jeton. Bien que get_token soit pratique, on peut également passer par le sérialiseur standadr :
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.tokens import AccessToken
credentials = {
'username': 'admin_user',
'password': 'secure_password_123'
}
# Validation des identifiants
auth_serializer = TokenObtainPairSerializer(data=credentials)
auth_serializer.is_valid(raise_exception=True)
# Extraction de l'utilisateur validé et génération du jeton
authenticated_user = auth_serializer.validated_data['user']
custom_token = AccessToken.for_user(authenticated_user)
final_jwt = str(custom_token)
Comparaison et Cas d'Usage
Le choix entre AccessToken.for_user et get_token dépend principalement du niveau de contrôle requis sur le jeton :
AccessToken.for_userretourne un objetAccessToken. C'est l'approche privilégiée si vous devez modifier la charge utile (ajouter des claims personnalisés), inspecter la date d'expiration ou ajuster les scopes avant la sérialisation.get_tokenretourne directement une chaîne de caractères. C'est la solution optimale pour une génération rapide et simple, lorsque le jeton standard suffit et qu'aucune altération de l'objet n'est prévue.
from django.contrib.auth import get_user_model
from rest_framework_simplejwt.tokens import AccessToken, get_token
UserModel = get_user_model()
account = UserModel.objects.get(username='test_user')
# Approche orientée objet
obj_token = AccessToken.for_user(account)
str_from_obj = str(obj_token)
# Approche fonctionnelle directe
str_from_func = get_token(account)
# Les deux chaînes produites sont fonctionnellement équivalentes
assert str_from_obj == str_from_func