How do I properly authenticate with OAuth using google-auth-oauthlib and Django?

I am building a Django project that works with video and needs to upload to Youtube. For this, I need oauth credentials. I am unable to authenticate with Oauth even though my redirect URI is correct and I am parsing the request for the code and passing it to the flow.
I am using google-auth-oauthlib and oauth to authenticate. Here is what the error looks like:
Traceback (most recent call last): File "/home/team/lotteh/venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner response = get_response(request) ^^^^^^^^^^^^^^^^^^^^^ File "/home/team/lotteh/venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 197, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/team/lotteh/venv/lib/python3.12/site-packages/sentry_sdk/integrations/django/views.py", line 89, in sentry_wrapped_callback return callback(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/team/lotteh/venv/lib/python3.12/site-packages/django/views/decorators/csrf.py", line 65, in _view_wrapper return view_func(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/team/lotteh/users/views.py", line 47, in google_auth_callback email, token, refresh = parse_callback_url(request, code) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/team/lotteh/users/oauth.py", line 66, in parse_callback_url flow.fetch_token(code=token_url) File "/home/team/lotteh/venv/lib/python3.12/site-packages/google_auth_oauthlib/flow.py", line 285, in fetch_token return self.oauth2session.fetch_token(self.client_config["token_uri"], **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/team/lotteh/venv/lib/python3.12/site-packages/requests_oauthlib/oauth2_session.py", line 406, in fetch_token self._client.parse_request_body_response(r.text, scope=self.scope) File "/home/team/lotteh/venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/clients/base.py", line 415, in parse_request_body_response self.token = parse_token_response(body, scope=scope) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/team/lotteh/venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/parameters.py", line 425, in parse_token_response validate_token_parameters(params) File "/home/team/lotteh/venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/parameters.py", line 432, in validate_token_parameters raise_from_error(params.get('error'), params) File "/home/team/lotteh/venv/lib/python3.12/site-packages/oauthlib/oauth2/rfc6749/errors.py", line 405, in raise_from_error raise cls(**kwargs)oauthlib.oauth2.rfc6749.errors.InvalidGrantError: (invalid_grant) Bad Request

And the views:

def google_auth(request):
    from django.shortcuts import redirect
    from users.oauth import get_auth_url
    import uuid
    url, state = get_auth_url(request, request.user.email if request.user.is_authenticated else None)
    print(state)
    request.session['state'] = state
    return redirect(url)

#@login_required
#@user_passes_test(is_superuser_or_vendor)

@csrf_exempt
def google_auth_callback(request):
    from users.oauth import parse_callback_url
    from security.middleware import get_qs
    from django.shortcuts import redirect
    from django.urls import reverse
    from django.conf import settings
    url = settings.BASE_URL + request.path + request.GET.urlencode()
    code = request.GET['code']
    email, token, refresh = parse_callback_url(request, code)
    from django.contrib.auth.models import User
    user = User.objects.filter(email=email).order_by('-last_seen').last()
    if not user:
        from users.username_generator import generate_username as get_random_username
        user = User.objects.create_user(email=e, username=get_random_username(), password=get_random_string(length=8))
        from django.contrib import messages
        messages.success(request, 'You are now subscribed, check your email for a confirmation. When you get the chance, fill out the form below to make an account.')
    user.profile.token = token
    user.profile.refresh_token = refresh
    user.profile.save()
    from django.contrib.auth import login as auth_login
    auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend')
    from django.contrib import messages
    messages.success(request, 'Successfully linked Google account')
    return redirect(reverse('/'))

And the helper functions seen above (users/oauth.py)

import google.oauth2.credentials
import google_auth_oauthlib.flow
from django.conf import settings
from django.urls import reverse
import os

flows = {}

def get_auth_url(request, email):
    flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(str(os.path.join(settings.BASE_DIR, 'client_secret.json')),
    scopes=['https://www.googleapis.com/auth/youtube.force-ssl',
        'https://www.googleapis.com/auth/youtube.upload',
        'https://www.googleapis.com/auth/youtube',
        'https://www.googleapis.com/auth/userinfo.email',
    ])
    flow.redirect_uri = settings.BASE_URL + reverse('users:oauth')
    authorization_url, state = None, None
    if email:
        authorization_url, state = flow.authorization_url(
            access_type='offline',
            include_granted_scopes='true',
            state=request.session.get('state'),
            login_hint=email,
            prompt='consent')
    else:
        authorization_url, state = flow.authorization_url(
            access_type='offline',
            include_granted_scopes='true',
            state=request.session.get('state'),
            prompt='consent')
    global flows
    flows[state] = flow
    return authorization_url, state

def get_user_info(credentials):
  """Send a request to the UserInfo API to retrieve the user's information.

  Args:
    credentials: oauth2client.client.OAuth2Credentials instance to authorize the
                 request.
  Returns:
    User information as a dict.
  """
  user_info_service = build(
      serviceName='oauth2', version='v2',
      http=credentials.authorize(httplib2.Http()))
  user_info = None
  try:
    user_info = user_info_service.userinfo().get().execute()
  except (errors.HttpError, e):
    logging.error('An error occurred: %s', e)
  if user_info and user_info.get('id'):
    return user_info
  else:
    raise Exception()

def parse_callback_url(request, token_url):
    global flows
    flow = flows[request.GET.get('state')]
    flow.fetch_token(code=token_url)
    credentials = flow.credentials
    return get_user_info(credentials)['email'], credentials.token, credentials.refresh_token

This is the line that fails, at the end:
flow.fetch_token(code=token_url)

Everything else seems to work properly. Please let me know if you know any way to fix this. I haven’t been able to get OAuth to work with a package, although I tried Django allauth. I am using Django 5, the latest version, on Ubuntu 24 with an Apache server. The web server is working and redirects to the callback URL, but the callback is broken. Please help, any help and ideas is appreciated.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật