Google API OAuth 2.0 无法验证错误 400:redirect_uri_mismatch

Google API OAuth 2.0 can't authenticate Error 400: redirect_uri_mismatch

我想创建一个对多个用户日历事件具有只读访问权限的应用程序。但是,我总是无法通过身份验证步骤。浏览器打开新的同意屏幕并显示 错误 400:redirect_uri_mismatch。这是我所做的:

为此,我在 google 控制台中设置了我的项目。我做了以下操作:

  1. 首先创建一个新项目,并在“APIs”页面上启用 Google 日历 API。
  2. 已配置同意屏幕
  3. 通过为应用程序类型选择 Web 应用程序和为身份验证方法选择 OAuth 2.0 创建凭据,并将“授权重定向 URI”设置为“http://localhost:8080”。现在网络应用程序在本地托管。
  4. 已在本地下载 credentials.json 文件。 json 文件如下:
{"web":
    {
        "client_id":"123234-jjjjj.apps.googleusercontent.com",
        "project_id":"ppppp-1234",
        "auth_uri":"https://accounts.google.com/o/oauth2/auth",
        "token_uri":"https://oauth2.googleapis.com/token",
        "auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs",
        "client_secret":"zzzzzzzzzzzzzzzzzz",
        "redirect_uris":["http://localhost:8080"],
        "javascript_origins":["http://localhost"]
    }
}

我使用下面的代码调用 google API:

import pickle
import os
from google_auth_oauthlib.flow import Flow, InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload
from google.auth.transport.requests import Request

def Create_Service(client_secret_file, api_name, api_version, *scopes):
    CLIENT_SECRET_FILE = client_secret_file
    API_SERVICE_NAME = api_name
    API_VERSION = api_version
    SCOPES = [scope for scope in scopes[0]]
    
    cred = None

    pickle_file = f'token_{API_SERVICE_NAME}_{API_VERSION}.pickle'
    
    if os.path.exists(pickle_file):
        with open(pickle_file, 'rb') as token:
            cred = pickle.load(token)

    if not cred or not cred.valid:
        if cred and cred.expired and cred.refresh_token:
            cred.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRET_FILE, SCOPES)
            cred = flow.run_local_server()

        with open(pickle_file, 'wb') as token:
            pickle.dump(cred, token)

    try:
        service = build(API_SERVICE_NAME, API_VERSION, credentials=cred)
        print(API_SERVICE_NAME, 'service created successfully')
        return service
    except Exception as e:
        print(e)
        return None


CLIENT_SECRET_FILE = 'token.json'
API_NAME = 'calendar'
API_VERSION = 'v3'
SCOPES = ['https://www.googleapis.com/auth/calendar.events.readonly']

service = Create_Service(CLIENT_SECRET_FILE, API_NAME, API_VERSION, SCOPES)
colors = service.colors().get().execute()

print(colors)

当我 运行 它时,浏览器会打开一个同意屏幕

Error 400: redirect_uri_mismatch. Then I follow http://localhost:8080/ and I see message "The authentication flow has completed. You may close this window."

并且在控制台中我看到以下错误:

 File "main.py", line 48, in <module>
    service = Create_Service(CLIENT_SECRET_FILE, API_NAME, API_VERSION, SCOPES)
  File "main.py", line 29, in Create_Service
    cred = flow.run_local_server()
  File "/home/ev/Projects/TIM/web/.venv/lib/python3.8/site-packages/google_auth_oauthlib/flow.py", line 480, in run_local_server
    self.fetch_token(authorization_response=authorization_response)
  File "/home/ev/Projects/TIM/web/.venv/lib/python3.8/site-packages/google_auth_oauthlib/flow.py", line 288, in fetch_token
    return self.oauth2session.fetch_token(self.client_config["token_uri"], **kwargs)
  File "/home/ev/Projects/TIM/web/.venv/lib/python3.8/site-packages/requests_oauthlib/oauth2_session.py", line 239, in fetch_token
    self._client.parse_request_uri_response(
  File "/home/ev/Projects/TIM/web/.venv/lib/python3.8/site-packages/oauthlib/oauth2/rfc6749/clients/web_application.py", line 203, in parse_request_uri_response
    response = parse_authorization_code_response(uri, state=state)
  File "/home/ev/Projects/TIM/web/.venv/lib/python3.8/site-packages/oauthlib/oauth2/rfc6749/parameters.py", line 268, in parse_authorization_code_response
    raise MismatchingStateError()
oauthlib.oauth2.rfc6749.errors.MismatchingStateError: (mismatching_state) CSRF Warning! State not equal in request and response.

那么,问题是如何以正确的方式通过 OAuth 2.0 向 google API 进行身份验证?

redirect_uri_mismatch

Web 应用程序使用重定向 uri 来指示您的应用程序准备接受来自 google 授权服务器的授权响应的位置。它基本上是 Web 服务器上准备响应授权的 URL。重定向 uris 仅用于 Web 应用程序。

在您的情况下,您正在创建一个已安装的应用程序 InstalledAppFlow,在这种情况下,您应该已经在 Google 开发人员控制台上创建了已安装的(桌面)凭据。桌面客户端能够从他们发送的位置接受授权响应,这通常是本地主机,因此授权服务器只是 returns 将令牌返回到调用的来源。

由于您的代码旨在通过向其提供 Web 应用程序凭据 运行 作为已安装的应用程序,这将导致它失败,因为该应用程序未发送正确的请求。

我这里有一个视频,将向您展示如何在 google 开发者控制台上创建 How to create Google Oauth2 installed application credentials