Troubleshooting 'invalid_grant' error in FastAPI backend during Google OAuth2 authentication

I’m stuck with a Google OAuth2 login issue in my React and FastAPI app. When I try to swap the auth code for tokens, I get this error:

Token data received from Google: {'error': 'invalid_grant', 'error_description': 'Malformed auth code.'}

I’ve double-checked my setup:

  • The auth code shows up in both frontend and backend logs
  • Redirect URI is the same everywhere (http://127.0.0.1:5173)
  • Client ID and secret are correct in the backend
  • I’ve tried decoding the token with unquote
  • I set response_type=‘code’ in the React component

My backend code looks like this:

@app.post('/google/auth')
async def handle_google_auth(auth_data: AuthData):
    try:
        clean_code = unquote(auth_data.code)
        print(f'Auth Code: {clean_code}')

        payload = {
            'client_id': GOOGLE_CLIENT_ID,
            'client_secret': GOOGLE_CLIENT_SECRET,
            'code': clean_code,
            'grant_type': 'authorization_code',
            'redirect_uri': 'http://127.0.0.1:5173',
        }

        response = requests.post('https://oauth2.googleapis.com/token', data=payload)
        token_info = response.json()
        print(f'Google Token Info: {token_info}')

        if 'id_token' in token_info:
            user_data = id_token.verify_oauth2_token(token_info['id_token'], requests.Request(), GOOGLE_CLIENT_ID)
            user_email = user_data['email']
        else:
            raise HTTPException(status_code=400, detail='Missing ID token from Google')

        return {'message': 'Auth successful', 'token': session_token, 'user': user_data}

    except Exception as e:
        raise HTTPException(status_code=500, detail=f'Server error: {str(e)}')

Why am I getting this ‘invalid_grant’ error? Is the React library giving me an ID token instead of an auth code? How can I fix this in my FastAPI backend? Help!

In my experience, the ‘invalid_grant’ error can be linked to timing issues, as Google’s authorization codes are short-lived and expire quickly. It is crucial to process and exchange the auth code immediately. Adding detailed logging for both the payload sent and the response received from Google can help identify any discrepancies during the exchange. Additionally, ensuring that your server’s clock is precisely synchronized with standard time can prevent such issues. If these steps do not resolve the error, consider using a dedicated library like ‘requests-oauthlib’ to handle the flow more reliably.

hey silvia, have u tried printing the raw auth_data.code before cleaning it? maybe theres an issue with the unquote step. also, double-check ur google console settings - sometimes the problem is there. good luck troubleshooting!

hm, that’s a tricky one! have you tried checking if the auth code is actually reaching your backend intact? maybe there’s some encoding issue happening during transmission?

also, just curious - what google oauth library are you using in react? some libraries handle the flow differently, so that might be worth looking into.

anyone else encountered similar issues? :thinking: