Usando la biblioteca djangorestframework_simplejwt , cuando POST a una vista personalizada
#urls.py path('api/token/', MyTokenObtainPairView.as_view(), name='token_obtain'), #views.py class MyTokenObtainPairView(TokenObtainPairView): serializer_class = MyTokenObtainPairSerializerPuedo obtener el siguiente token de acceso
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNTkwOTEwNjg0LCJqdGkiOiI3M2MxYmZkOWNmMGY0ZjI3OTY4MGY0ZjhlYjA1NDQ5NyIsInVzZXJfaWQiOjExfQ.5vs0LmNGseU6rtq3vuQyApupxhQM3FBAoKAq8MUukIBOOYfDAV9guuCVEYDoGgK6rdPSIq2mvcSxkILG8OH5LQAl ir a https://jwt.io/ puedo ver que la carga útil está actualmente
{ "token_type": "access", "exp": 1590910684, "jti": "73c1bfd9cf0f4f279680f4f8eb054497", "user_id": 11 }Entonces, podemos ver que la segunda parte del token es la carga útil, que contiene las reclamaciones.
He explorado cómo agregar más información al cuerpo de la Respuesta y ahora me gustaría saber cómo personalizar los datos de la Carga útil agregando el reclamo iat , el nombre de usuario y la fecha de hoy.
Como ya creó una subclase para la vista deseada (MyTokenObtainPairView) y una subclase para su serializador correspondiente (MyTokenObtainPairSerializer), agregue lo siguiente al serializador
class MyTokenObtainPairSerializer(TokenObtainPairSerializer): ... @classmethod def get_token(cls, user): token = super().get_token(user) # Add custom claims token['iat'] = datetime.datetime.now() token['user'] = user.username token['date'] = str(datetime.date.today()) return tokenLuego, cuando publique en esa misma ubicación, obtendrá un token de acceso como este
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNTkwOTE0MTk4LCJqdGkiOiJhZDZmNzZhZjFmOGU0ZWJlOGI2Y2Y5YjQ4MGQzZjY2MiIsInVzZXJfaWQiOjExLCJpYXQiOjE1OTA5MTc0OTgsInVzZXIiOiJ0aWFnbyIsImRhdGUiOiIyMDIwLTA1LTMxIn0.-5U9P-WWmhlOenzCvc6b7_71Tz17LyNxe_DOMwwqH4RqrNsilVukEcZWFRGupLHRZjIvPya2QJGpiju9ujzQuwAl usar JWT, puede ver que la carga útil cambia en consecuencia
{ "token_type": "access", "exp": 1590914198, "jti": "ad6f76af1f8e4ebe8b6cf9b480d3f662", "user_id": 11, "iat": 1590917498, "user": "tiago", "date": "2020-05-31" }En tus vistas.py
from rest_framework_simplejwt.tokens import RefreshToken from rest_framework.response import Response from rest_framework.decorators import api_view, permission_classes from rest_framework.permissions import AllowAny from decouple import config from django.contrib.auth import authenticate import jwt @api_view(['POST']) @permission_classes([AllowAny]) def get_tokens_for_user(request): username = request.POST.get("username") password = request.POST.get("password") user = authenticate(username=username, password=password); if user is not None: refreshToken = RefreshToken.for_user(user) accessToken = refreshToken.access_token decodeJTW = jwt.decode(str(accessToken), config('SECRET_KEY'), algorithms=["HS256"]); # add payload here!! decodeJTW['iat'] = '1590917498' decodeJTW['user'] = 'tiago' decodeJTW['date'] = '2020-05-31' #encode encoded = jwt.encode(decodeJTW, config('SECRET_KEY'), algorithm="HS256") return Response({ 'status': True, 'refresh': str(refreshToken), 'access': str(encoded), }) else: return Response({ 'status': False }) # No backend authenticated the credentialsEn tu urls.py
from django.urls import path, include from .views import get_tokens_for_user urlpatterns = [ path('login/', get_tokens_for_user, name="login"), ]En tu configuración.py
from pathlib import Path from datetime import timedelta from decouple import config ... # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = config('SECRET_KEY') # Application definition INSTALLED_APPS = [ ... # Rest 'rest_framework', ... ] REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework_simplejwt.authentication.JWTAuthentication', ], 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', ] } # JWT # https://django-rest-framework-simplejwt.readthedocs.io/en/latest/settings.html SIMPLE_JWT = { 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60), 'REFRESH_TOKEN_LIFETIME': timedelta(days=1), 'AUTH_HEADER_TYPES': ('Bearer',), 'SIGNING_KEY': config('SECRET_KEY'), 'VERIFYING_KEY': config('SECRET_KEY'), 'ALGORITHM': 'HS256', }En su directorio raíz agregue .env
SECRET_KEY = 'ep@4ojr4m!h73y2j(stackoverflow)kra1*@tq$5el626wf@&p60)7u!6552+-'Valores de tiempo de ejecución
decodeJTW = { 'token_type': 'access', 'exp': 1612651527, 'jti': '7f415b28610348468ce74ec0f480fad1', 'user_id': 2, 'iat': '1590917498', 'user': 'tiago', 'date': '2020-05-31' } encode = { "status":true, "refresh":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTYxMjczNDU0NywianRpIjoiMDQ0MDI3ZTQzMTc2NDFiNDhhOGI2MjU4MjE4ZGZjNDkiLCJ1c2VyX2lkIjoyfQ.Qf0YfJLAmdYuavDHVng7Bwjmka551G6c1Gi4e-UdRuc", "access":"b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjEyNjUxNzQ3LCJqdGkiOiI2OWEzNjYwYjYxMTk0MzVjYjljZTA0OGQ3MmE1ODk1YSIsInVzZXJfaWQiOjIsImlhdCI6IjE1OTA5MTc0OTgiLCJ1c2VyIjoidGlhZ28iLCJkYXRlIjoiMjAyMC0wNS0zMSJ9.XUMvhL13zDZdbjYYPkYnwlZoHN6U7Zc3xUzXsKoVj2I'" }Cuando vine aquí buscando una solución para agregar el vencimiento del token a la respuesta mientras trabajaba condj-rest-auth y djangorestframework_simplejwt, encontré una solución en el código (¿aparentemente sin documentar?):
Hay una configuración llamada JWT_AUTH_RETURN_EXPIRATION que, si se establece en True, agrega la caducidad a la respuesta de la siguiente manera:
{ "access_token": "ACCESS_TOKEN_STRING", "refresh_token": "REFRESH_TOKEN_STRING", "user": { "pk": PK, "email": "USER_EMAIL" }, "access_token_expiration": "2021-02-10T10:40:46.883715Z", "refresh_token_expiration": "2021-02-11T10:35:46.883728Z" }y lo mismo para actualizar:
{ "access": "ACCESS_TOKEN_STRING", "access_token_expiration": "2021-02-10T10:47:57.325545Z" }