Drf-social-oauth2: request.user is AnonymousUser
Я пытаюсь использовать drf-social-oauth2 для аутентификации и авторизации. Я настроил его, используя документацию по ссылке выше. Но документации не хватает. Я не смог найти в документации, как изменить некоторые настройки.
Когда я отправляю запрос на /auth/token/
, вот какой ответ я получаю:
{
"access_token": "KQP6l5nHezWlFO3Ixwz4IIFNUjkvEp",
"expires_in": 36000,
"token_type": "Bearer",
"scope": "read write",
"refresh_token": "rmyOZJPQE6Z1eqbpihr2Ux6YMDN1LU"
}
Но я хочу использовать JWT с пользовательскими утверждениями и не могу найти, как это сделать в документации по ссылке выше.
Мой вопрос на данный момент заключается в том, как я могу использовать JWT вместо Bearer. И как я могу включить пользовательские требования в JWT-токены, используя drf-social-oauth2 ?
Если можете, пожалуйста, укажите мне на документацию с более подробной информацией о drf-social-oauth2. Единственное, что я нашел для настройки токена, это это в этой документации.
РЕДАКТИРОВАТЬ 1
Мне удалось использовать JWT-токены, добавив ACTIVATE_JWT = True
в мой settings.py
файл. Мне также удалось включить пользовательские требования в токен, переопределив функцию create_token_response
класса TokenView
и переопределив конечную точку auth/token
, как показано ниже:
from drf_social_oauth2.views import TokenView
import json
from jose import jwt
from django.conf import settings
class CustomTokenView(TokenView):
def create_token_response(self, request):
response_data = super().create_token_response(request)
print("+++++++++++++++++++++++++++++++++++++++++++++")
print(request.user)
print(request.user.id)
print("+++++++++++++++++++++++++++++++++++++++++++++")
url, headers, body, status = response_data
token_data = json.loads(body)
access_token = token_data.get("access_token")
decoded_token = jwt.decode(
access_token, settings.SECRET_KEY, algorithms=["HS256"]
)
decoded_token["custom_claim"] = "custom_value"
updated_access_token = jwt.encode(
decoded_token, settings.SECRET_KEY, algorithm="HS256"
)
token_data["access_token"] = updated_access_token
modified_body = json.dumps(token_data)
return url, headers, modified_body, status
А в urls.py:
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView
from account.views import CustomTokenView
urlpatterns = [
# oauth
path("auth/token/", CustomTokenView.as_view(), name="token_obtain"),
path("auth/", include("drf_social_oauth2.urls", namespace="drf")),
# admin
path("admin/", admin.site.urls),
# user account
path("api/account/", include("account.urls", namespace="account")),
path("api-auth/", include("rest_framework.urls", namespace="rest_framework")),
# api schema
path("api/schema/", SpectacularAPIView.as_view(), name="schema"),
path(
"api/schema/docs/",
SpectacularSwaggerView.as_view(url_name="schema"),
name="swagger-ui",
),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Но теперь я хочу включить информацию о пользователе в jwt-токен. Но когда я печатаю request.user
и request.user.id
в функции create_token_response
, упомянутой выше, как показано ниже:
print("+++++++++++++++++++++++++++++++++++++++++++++")
print(request.user)
print(request.user.id)
print("+++++++++++++++++++++++++++++++++++++++++++++")
вывод:
+++++++++++++++++++++++++++++++++++++++++++++
AnonymousUser
None
+++++++++++++++++++++++++++++++++++++++++++++
Пользователем является AnonymousUser
, а идентификатором - None
.
Я сделал то, что хотел, сделав примерно следующее:
import json
from jose import jwt
from django.conf import settings
from oauth2_provider.models import AccessToken
class CustomTokenView(TokenView):
def create_token_response(self, request):
response_data = super().create_token_response(request)
url, headers, body, status = response_data
if status == 400:
return response_data
# Extract token
token_data = json.loads(body)
access_token = token_data.get("access_token")
access_token_object = AccessToken.objects.get(token=access_token)
# Extract the email from the request and get the user with that email
user_email = access_token_object.user
user = User.objects.get(email=user_email)
# Decode the token and add custom claims and encode the token again
decoded_token = jwt.decode(
access_token, settings.SECRET_KEY, algorithms=["HS256"]
)
decoded_token["token_type"] = "access"
decoded_token["user_id"] = user.id
decoded_token["email"] = user.email
decoded_token["exp"] = access_token_object.expires
updated_access_token = jwt.encode(
decoded_token, settings.SECRET_KEY, algorithm="HS256"
)
# Update the token with new tokens containing custom claims
token_data["access_token"] = updated_access_token
modified_body = json.dumps(token_data)
response_data = url, headers, modified_body, status
return response_data
и переопределите конечную точку auth/token/
, чтобы использовать это пользовательское представление:
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView
from account.views import CustomTokenView
urlpatterns = [
# oauth
path("auth/token/", CustomTokenView.as_view(), name="token_obtain"),
path("auth/", include("drf_social_oauth2.urls", namespace="drf")),
# admin
path("admin/", admin.site.urls),
# user account
path("api/account/", include("account.urls", namespace="account")),
path("api-auth/", include("rest_framework.urls", namespace="rest_framework")),
# api schema
path("api/schema/", SpectacularAPIView.as_view(), name="schema"),
path(
"api/schema/docs/",
SpectacularSwaggerView.as_view(url_name="schema"),
name="swagger-ui",
),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)