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?
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"},
)