[Solved]-Django, Djoser social auth : State could not be found in server-side session data. status_code 400

2👍

ok so this is a common problem while you are working with social auth. I had the same problem for so many times.

The flow:

  1. make a request to http://127.0.0.1:8000/auth/o/google-oauth2/?redirect_uri=http://localhost:3000/ (example)

  2. you will get a authorization_url. if you notice in this authorization_url there is a state presented . this is the ‘state of server side’.

  3. now you need to click the authorization_url link.Then you will get the google auth page.After that you will be redirect to your redirect url with a state and a code. Remember this state should be the same state as the server side state .(2)

  4. make post req to http://127.0.0.1:8000/auth/o/google-oauth2/?state=''&code=''.
    if your states are not the same then you will get some issue.

everytime you wanna login , you need to make a request to http://127.0.0.1:8000/auth/o/google-oauth2/?redirect_uri=http://localhost:3000/
and then to http://127.0.0.1:8000/auth/o/google-oauth2/?state=''&code='' thus you will get the same state.

1👍

Without necessary detailed information, I can only tell 2 possible reasons:

  1. You overrode backend with improper session operations(or the user was logged out before auth was finished).
  2. Front-end used incorrect state parameter

You could test social login without front-end, let’s say if you’re trying to sign in with Google:

  1. Enter the social login URL in browser, like domain.com:8000/login/google-oauth2/
  2. Authorize
  3. See if the page redirected to your default login page correctly

If yes, then probably you need to check your front-end code, and if no, then check your backend code.

At the end, if you’re not so sensitive to the potential risk, you could also override GoogleOAuth2 class as following to disable state check:

from social_core.backends import google

class GoogleOAuth2(google.GoogleOAuth2):
    STATE_PARAMETER = False
👤YKL

1👍

Finally, I’ve reached a point where everything is functioning flawlessly, both on the local environment and in production. The core issue turned out to be related to cookies and sessions. The correct solution was to trick the backend server into perceiving the request as if it were coming from "localhost:8000" instead of "localhost:3000". This entails ensuring that the backend domain remains consistent.

To achieve this, there are two feasible approaches:

  1. Serve Frontend Build from the Server: The server should host the compiled version of the frontend. By doing this, the frontend will always share the same domain as the backend.

  2. Django View with Google Auth Logic: Implement a simple Django view and associate an empty template with it. This template should solely contain a script tag incorporating the necessary logic to manage Google authentication. The process involves the following steps:

    • When a user clicks on "Sign in with Google," they are directed to this view.
    • The view manages the authentication process, and upon completion, it retrieves the access token.
    • The access token is then passed to the frontend via URL parameters.

In my case, I opted for the second approach, as it suited my requirements better. The procedure involves creating a basic view and linking it to a template. This way, when a user selects "Sign in with Google," the corresponding view is triggered. Subsequently, the view takes over the authentication process. Once the access token is obtained, it is transferred to the specified URL.

0👍

I think you may need some changes in you authorizing flow in step NO.3 and 4.

3.Authentication with google and redirection back to the front-end with a state and code parameters on the url.
4.Front-end get the data form url and post data to back-end to verify that the state received is equal to the generated on the point (1).

maybe you should redirect back to server side after google’s authorization.

then at the server side, do the check! validate the state and code (maybe do more things).

then let server redirect to the front-end site you wanted to before.

for some reason, redirect to front-end directly will miss the param.. 🙂

Leave a comment