【问题标题】:Google API OAuth 2.0 can't authenticate Error 400: redirect_uri_mismatchGoogle API OAuth 2.0 无法验证错误 400:redirect_uri_mismatch
【发布时间】:2021-06-28 20:08:15
【问题描述】:

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

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

  1. 首先创建一个新项目,并在“API”页面上启用 Google Calendar API。
  2. 配置同意屏幕
  3. 通过选择Web Application作为应用程序类型和OAuth 2.0作为身份验证方法创建凭据,并将“Authorized redirect URIs”设置为“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)

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

错误 400:redirect_uri_mismatch。 然后我点击 http://localhost:8080/ 并看到消息“身份验证流程已完成。您可以关闭此窗口。”

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

 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 进行身份验证?

【问题讨论】:

  • 我认为在您的情况下,Error 400: redirect_uri_mismatch. 问题的原因可能是由于 Google 端的 http://localhost:8080"redirect_uris":["http://localhost:8080"], http://localhost:8080/ 之间的差异和脚本端.在您的情况下,当您将Google端的重定向uri从http://localhost:8080更改为http://localhost:8080/并再次测试时,您会得到什么结果?因为脚本创建 http://localhost:8080/ 作为重定向 uri。如果我误解了您的情况,我深表歉意。

标签: python google-api google-oauth google-calendar-api google-api-python-client


【解决方案1】:

redirect_uri_mismatch

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

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

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

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

【讨论】:

  • DaImTo 我的代码在 localhost:8080 启动服务器,所以据我所知,我使用网络应用程序。无论如何,感谢您的回复!
  • 实际上并不是它有一个斜杠和一个端口号,它不是您可以在代码中配置的东西。安装的应用程序使用 urn:ietf:wg:oauth:2.0:oob 不是真正的 localhost 这意味着 localhost 但重定向 uri 需要完全匹配。
猜你喜欢
  • 2021-11-05
  • 2020-11-08
  • 2021-10-16
  • 2014-02-09
  • 2015-04-03
  • 2021-11-13
  • 2021-10-14
  • 2022-11-05
  • 2016-02-21
相关资源
最近更新 更多