I'm making a web app with Django 3.2 (Python 9) as backend and ReactJs 17 as frontend with a Graphene(GraphQL) API in between. ReactJs uses Apollo Client Provider 3.4 to perform the API queries and mutations.
I'm using the django-graphql-auth package to authenticate my users and I store the user's authentications token in the browser's localStorage that I then put in the headers of the Apollo Provider.
Everything works well until there.
Now, the problem is that the user should be able to download files by clicking on a link in the frontend. This link will redirect to a backend Django view where a file is put in a HttpResponse. The user will be prompt to accept downloading the file.
However, the file is generated based on the user whom request it (on the user's Group to be more precise). So in my Django view, I use the request.user.groups variable to generate the file that will be downloadable.
Here is the problem: on the backend side, the user is still anonymous while authenticated in the frontend.
How can I authenticate the user in the backend when (s)he logs in in the frontend ?
Can I simply pass the request.user value from React to Django's download view? If yes, how is it possible ?
Thanks in advance for your help.
CodePudding user response:
I have found a solution.
I just include the user's JWT authentication token in the url pointing to the backend view.
# urls
from django.urls import path
from src import views
urlpatters = [
path("download/<str:user_auth_token>/", views.my_view),
]
My Django view in the backend then gets the user from the token's payload. An error is thrown if the token isn't valid.
from graphql_jwt.utils import get_payload, get_user_by_payload
from src.models import AppUser
def get_user_from_token(jwt_token: str) -> AppUser:
"""Get the user from the JWT token received from the frontend"""
return get_user_by_payload(get_payload(jwt_token))
So the user is still not authenticated in the backend. I don't get the user from the request but from the token:
# view
from django.core.handlers.wsgi import WSGIRequest
def my_view(request: WSGIRequest, user_auth_token: str):
user = get_user_from_token(user_auth_token)
# Do something...
I only need it on one view, but I've seen that instead of sending the token through the url, I can also put it in a cookie and create a middleware in the backend to read it and get the user from it.
This could be handy if you want to use multiple backend views where you need to fetch the user's data.
