Search code examples
pythongoogle-oauthfastapi

How do I fix a "CSRF Warning! State not equal in request and response." error when trying to log in with Google using FastAPI?


I get redirected fine to Google's consent screen, but after consenting, I get hit with the authlib.integrations.base_client.errors.MismatchingStateError: mismatching_state: CSRF Warning! State not equal in request and response. error. The weird part is I've seen this exact way of doing it a few different times, and I follow the steps precisely, but in my case it doesn't work for some reason.

Here's the minimal reproduceable example:

from fastapi import FastAPI, Request
from starlette.middleware.sessions import SessionMiddleware
from authlib.integrations.starlette_client import OAuth

oauth = OAuth()
oauth.register(
    name="google",
    client_id="my_google_client_id",
    client_secret="my_google_client_secret",
    authorize_url="https://accounts.google.com/o/oauth2/auth",
    access_token_url="https://accounts.google.com/o/oauth2/token",
    client_kwargs={"scope": "openid profile email"},
)

app = FastAPI()
app.add_middleware(SessionMiddleware, secret_key="my_secret_key")


@app.get("/google_login")
async def google_login(request: Request):
    return await oauth.google.authorize_redirect(
        request, redirect_uri="http://localhost:8000/google_auth"
    )


@app.get("/google_auth")
async def google_auth(request: Request):
    token = await oauth.google.authorize_access_token(request)
    user = await oauth.google.parse_id_token(request, token)
    return user

This code looks exactly the same as a lot of tutorials on how to do this, but it doesn't work, why?


Solution

  • I don't know why, but replacing the authorize_url and access_token_url with a server_metadata_url fixes the problem. The oauth.register part should therefore look like this:

    oauth.register(
        name="google",
        client_id="my_google_client_id",
        client_secret="my_google_client_secret",
        server_metadata_url="https://accounts.google.com/.well-known/openid-configuration",
        client_kwargs={"scope": "openid profile email"},
    )