djoser icon indicating copy to clipboard operation
djoser copied to clipboard

`State could not be found in server-side session data.` with React Frontend.

Open mabdullahadeel opened this issue 3 years ago • 23 comments

Hey everyone.

I am facing this State could not be found in server-side session data. issue with my app. I am pretty sure that I have configured everything properly since everything is working fine in the Postman and I am able to create user from the postman.

For the frontend, I am using nextjs. Making requests with code and state always comes back with "State could not be found in server-side session data." no matter what. Not sure where exactly is this coming from?

The fact that it is working with Postman might be because of the cookies sessionid and csrftoken which I am not very sure about.

If any mod can please help regarding this, would be very helpful.

Thanks

mabdullahadeel avatar Aug 14 '21 22:08 mabdullahadeel

@mabdullahadeel Did you fix it ? I'm facing the same issue figuring out how to do the requests using axios with the sessionid cookie as Postman does.

dirodriguezm avatar Sep 21 '21 19:09 dirodriguezm

@mabdullahadeel Did you fix it ? I'm facing the same issue figuring out how to do the requests using axios with the sessionid cookie as Postman does.

No I was not able to figure it out directly. I ended up using another library for social auth named dj-rest-auth here. This lib uses django-allauth and provides a lot more control.

mabdullahadeel avatar Sep 21 '21 20:09 mabdullahadeel

Can't get this to work either using Postman or NuxtJS. Getting the same error. Not sure what alternatives there are if one still wishes to keep Djoser.. any pointers? Did you end up still using Djoser but adding dj-rest-auth to it? If so, I would love to see how you implemented it. It really sucks because this turned out to be really difficult to debug. @mabdullahadeel

Tobeyforce avatar Sep 22 '21 21:09 Tobeyforce

Can't get this to work either using Postman or NuxtJS. Getting the same error. Not sure what alternatives there are if one still wishes to keep Djoser.. any pointers? Did you end up still using Djoser but adding dj-rest-auth to it? If so, I would love to see how you implemented it. It really sucks because this turned out to be really difficult to debug. @mabdullahadeel

@Tobeyforce I completely ditched djoser as I couldn't find any direct solution to the problem. You can find the full implementation of the code here in this repo I would love to help if you need any. Also, dj-rest-auth has way more control and functionality than djoser. So it's a good consideration. The only thing is you have to use it with django-allauth Thanks

mabdullahadeel avatar Sep 22 '21 21:09 mabdullahadeel

@haxoza I think this should be high priority. This means the most prominent frameworks as of right now cannot implement social auth (from my understanding it has to do with sessions which front end apps do not add by default, while something like Postman will add it) An update would be much appreciated, or me and others will be forced to migrate from djoser.

@mabdullahadeel Thanks for the reply & link to repo, I will check it out :). I'm torn whether or not to switch as my application is quite massive and I've already spent a ton of time customizing various things for djoser. But perhaps it's the best long term solution for me.

Tobeyforce avatar Sep 22 '21 23:09 Tobeyforce

same issue, no good answers from anyone on vercels discord, django discord, or reactiflux nextjs discord

tonydattolo avatar Oct 15 '21 01:10 tonydattolo

same issue, no good answers from anyone on vercels discord, django discord, or reactiflux nextjs discord

Just ditch djoser. I followed @mabdullahadeel advice and switched to dj-rest-auth even though it was a pain to switch out auth, it now feels worth it once I got social auth up and running. Sunscrapers simply do not seem to care about Djoser anymore. The package should be considered unmaintained and frankly they should hand over the repo to someone else, or stop saying that it supports social auth when they don't seem to care about it when it breaks.

Tobeyforce avatar Oct 15 '21 08:10 Tobeyforce

I've been debugging in the backend. It looks like this might be a social_core issue not djoser. The state session in the backend that is set to be passed to Google is not persisting for some reason.

If you look at social_core/backends/oauth.py on line 78 is where the issue occurs and it's a result of the states not matching. Perhaps that get_state_or_create method isn't working as intended

Perhaps this could be a NextJS specific issue as well, it looks like maybe there is some error with this failing because it doesn't have access to sessionid data from the frontend maybe.

tonydattolo avatar Oct 15 '21 15:10 tonydattolo

https://stackoverflow.com/questions/57305141/react-django-rest-framework-session-is-not-persisting-working/57316231#57316231

use this method, will handle this problem, thanks from @tonydattolo for helping me to find sooner the solution

Painkiller1991 avatar Oct 28 '21 14:10 Painkiller1991

From what I read may be due I host my react application in localhost:3000 and my DRF server in localhost:8000 But can't seem to find any solution. Would you recommend me unininstalling Djoser and just trying another library for social auth? Thanks

bialotomas avatar Mar 11 '22 22:03 bialotomas

I have this working when running my React front end at localhost:3000 and and the backed at localhost:8000 following the steps from: https://stackoverflow.com/questions/57305141/react-django-rest-framework-session-is-not-persisting-working/57316231#57316231. When I move the backend to heroku however I am getting State could not be found in server-side session data.

devin-glauner avatar Jun 21 '22 00:06 devin-glauner

https://stackoverflow.com/questions/57305141/react-django-rest-framework-session-is-not-persisting-working/57316231#57316231

this answer will work 200 percent

abdullahzulfiqar-PL avatar Jul 28 '22 05:07 abdullahzulfiqar-PL

https://stackoverflow.com/questions/57305141/react-django-rest-framework-session-is-not-persisting-working/57316231#57316231

this answer will work 200 percent

@abdullahzulfiqar-PL Actually back then when I was having this issue, I tried this solution but did not work for me.

It might work now but I have not used the library since then.

mabdullahadeel avatar Jul 28 '22 08:07 mabdullahadeel

@mabdullahadeel you was right, But Finally I reach on a point where everything is working 200 percent fine, on local as well as production. The issue was totally related to the cookies and sessions: So rite answer typo is make it look to your backend server as if the request is coming from localhost:8000 not localhost:3000, means backend domain should be same always. For making it possible you have two ways: 1: server should serve the build of frontend then you fronend will always be on the same domain as backend. 2: make a simple view in django and attach an empty template to it with only script tag including logic to handle google auth. always when you click on signing with google just move back you your that view and handle the process and at the end when you get back your accesstoken pass it to frontend through params. I used 2nd approach as this was appropriate for me.

backend script code:

ParadiseCompetitions

abdullahzulfiqar653 avatar Aug 10 '22 08:08 abdullahzulfiqar653

is their python code that handles all process auth with Djoser in the backend! really this is issue stack me I need handle all processes in backend with python code

younis-bash avatar Aug 13 '22 09:08 younis-bash

is their python code that handles all process auth with Djoser in the backend! really this is issue stack me I need handle all processes in backend with python code

@younis-ba can you please elaborate? I couldn't get your point.

mabdullahadeel avatar Aug 13 '22 11:08 mabdullahadeel

@younis-ba and @mabdullahadeel I made a video on it that how to resolve this issue! https://drive.google.com/file/d/17bTCCN8-UDRCfIbAPpVyJyIQKVqFdOeO/view?usp=sharing please watch and sorry for the late response

abdullahzulfiqar653 avatar Aug 15 '22 12:08 abdullahzulfiqar653

@abdullahzulfiqar-PL thank you for sharing the solution the main problem is that when request auth URL its stores the session id in a cookie after the get code and state its needs the session id in the request in headers I go deep into Djoser after that, i implement an experiment that grab the session id from cookie and sent likes this respon=requests.post( url="https://domain/auth/social/o/google-oauth2/", data={ 'code': "code", 'state': "state" } ,
headers={ 'Content-Type':'application/x-www-form-urlencoded', 'Cookie':'sessionid=sessionid' }, ) then it successfully registers the user but a new problem arrows me that when react in port 5000 and backend in port 8000 the session id not stored in cookies I want to stop a session and make it with none inside or make the session id possible store in multisite

younis-bash avatar Aug 15 '22 19:08 younis-bash

@abdullahzulfiqar785 your approach didn't work for me. After getting the request in the GoogleCodeVerificationView(TemplateView), it doesn't start further actions written in the script tag of google.html file. neither axios.get(/api/accounts/auth/o/google-oauth2/redirect_uri=${redirect_uri}/api/accounts/google get called nor axios.post(/api/accounts/auth/o/google-oauth2/?${formBody}) get called. How can you say with 200% confidence?

babor99 avatar Aug 30 '22 05:08 babor99

our approach didn't work for me. After getting the request in the GoogleCodeVerificationView(TemplateView), it doesn't start further actions written in the script tag of google.html file.

I think you are very bignner, well I think you have not provided redirect uris if your get request is not working then you should check and set the logic! in curley braces redirect_uri variable is coming from my view and in view I am getting it from settings .py you should change it and also inside script I have some logic like flag handling using if you should have look on that too!

abdullahzulfiqar653 avatar Aug 30 '22 13:08 abdullahzulfiqar653

I have changed all the stuffs accordingly. But goes in vain

babor99 avatar Sep 11 '22 13:09 babor99

I've been debugging in the backend. It looks like this might be a social_core issue not djoser. The state session in the backend that is set to be passed to Google is not persisting for some reason.

If you look at social_core/backends/oauth.py on line 78 is where the issue occurs and it's a result of the states not matching. Perhaps that get_state_or_create method isn't working as intended

Perhaps this could be a NextJS specific issue as well, it looks like maybe there is some error with this failing because it doesn't have access to sessionid data from the frontend maybe.

This is not a Next.js specific problem. I am using react as FE and facing the exact same problem and found the same method that is not working. What i figured that the place when storing the state and pulling it is not the same.

WeaverArtemSoft avatar Nov 13 '22 07:11 WeaverArtemSoft

Hi, I was facing the same issue but I was able to solve it and was able to get the JWT Access Token and Refresh Token for Google Login without replacing DJoser.

I have my Front-end in React JS and Backend in DJango (DRF, DJoser, DJoser Social Login, drf_social_oauth2, social_django).

Problem: "non_field_errors": ["Invalid state has been provided."], I was getting this response when I performed POST request to http://127.0.0.1:8000/auth/o/google-oauth2/?state=[state]&code=[code]

Solution: The problem is probably with session storage. The following steps helped me solve it.

1. Add this to the React App where you are making HTTP/HTTPS Requests:

import axios from "axios";

axios.defaults.withCredentials = true;

Source: https://stackoverflow.com/questions/57305141/react-django-rest-framework-session-is-not-persisting-working/57316231#57316231

2. In your DJango settings.py, set the following settings:

	CORS_ALLOW_ALL_ORIGINS = True
	CORS_ALLOW_HEADERS = ["Authorization", "Content-Type", "Accept"]
	CORS_ALLOW_CREDENTIALS = True

CORS_ALLOW_HEADERS = ["*"], this stopped working for some unknown reason. I had to specify the headers I was using.

Source: https://stackoverflow.com/questions/57305141/react-django-rest-framework-session-is-not-persisting-working/57316231#57316231

3. In addition, make sure "corsheaders.middleware.CorsMiddleware" is the first thing in the middleware.

MIDDLEWARE = [
    		"corsheaders.middleware.CorsMiddleware",
    		...
    		]

I am not sure whether this helped in fixing the issue or not but I made this change which might have also played some role in fixing this issue.

Source: GitHub Copilot

GitHub Copilot:

Make sure that corsheaders.middleware.CorsMiddleware is the first middleware in your MIDDLEWARE. This ensures that the django-cors-headers middleware is the first to process the request and the last to process the response, which is necessary for it to correctly handle the CORS headers.

4. Change your React App host:

This is the major change which helped in solving the problem.

My React App was being hosted at: localhost:3000/ and DJango at 127.0.0.1:8000/

I changed hosting of my React App from localhost:3000 -> 127.0.0.1:3000

So for example I was making my Google Login Request from 127.0.0.1/login-register, the route looked like: 127.0.0.1:3000/login-register -> Google Login Screen -> (Redirect) 127.0.0.1:3000/login-register

In my case I get redirected to 127.0.0.1:3000/login-register, so make sure the redirect uri is also changed to 127.0.0.1

My request looked like: Was axios.get("http://127.0.0.1:8000/auth/o/google-oauth2/?redirect_uri=http://localhost:3000/login-register"); Now
axios.get("http://127.0.0.1:8000/auth/o/google-oauth2/?redirect_uri=http://127.0.0.1:3000/login-register");

Don't forget to add or change your base url from localhost:3000 -> 127.0.0.1:3000 in Authorized redirect URIs at Google Cloud -> Credentials.

Source: https://stackoverflow.com/questions/57305141/react-django-rest-framework-session-is-not-persisting-working/57316231#57316231

  1. Add changes to your DJoser -> SOCIAL_AUTH_ALLOWED_REDIRECT_URIS in settings.py: Now add the your updated redirect uri to:
DJOSER = {
		    # Your rest of DJoser Settings:
		    "SOCIAL_AUTH_ALLOWED_REDIRECT_URIS": [
			"http://localhost:3000/login-register",
			"http://127.0.0.1:3000/login-register", # (Update)
		    ],
		}

After applying the following changes, I was able to login with google and get Access and Refresh Tokens.

NOTE: I spent good time at fixing this issue. These are the changes which helped me in properly implementing Google Social Login. I hope these steps also help you fix this issue if you are facing. I have also attached screenshot of successful creation of User in the database. I have tried my best to share everything that has helped me.

User created: Screenshot from 2024-04-07 19-57-32

Getting the Access Token Refresh Token and Logged In: Screenshot from 2024-04-07 20-01-23

muzammilmalik01 avatar Apr 07 '24 15:04 muzammilmalik01