谷歌 Oauth2-redirect_uri_mismatch 400

Ela*_*ayA 4 python oauth-2.0 google-api-python-client gmail-api google-developers-console

你好,我正在尝试将 Google Sign In 集成到我的 python 脚本中,并且运行此错误:

\n

访问被阻止:此应用程序\xe2\x80\x99s请求无效

\n

您无法\xe2\x80\x99 登录,因为此应用发送了无效请求。您可以稍后再试,或者联系开发人员解决此问题。了解有关此错误的更多信息

\n

如果您是此应用程序的开发人员,请参阅错误详细信息

\n

错误 400:redirect_uri_mismatch

\n

我尝试运行的 python 脚本是来自 Google 来源的基本脚本:

\n
# import the required libraries\nfrom googleapiclient.discovery import build\nfrom google_auth_oauthlib.flow import InstalledAppFlow\nfrom google.auth.transport.requests import Request\nimport pickle\nimport os.path\nimport base64\nimport email\nfrom bs4 import BeautifulSoup\n\n# Define the SCOPES. If modifying it, delete the token.pickle file.\nSCOPES = ['https://www.googleapis.com/auth/gmail.readonly']\n\ndef getEmails():\n    # Variable creds will store the user access token.\n    # If no valid token found, we will create one.\n    creds = None\n\n    # The file token.pickle contains the user access token.\n    # Check if it exists\n    if os.path.exists('token.pickle'):\n\n        # Read the token from the file and store it in the variable creds\n        with open('token.pickle', 'rb') as token:\n            creds = pickle.load(token)\n\n    # If credentials are not available or are invalid, ask the user to log in.\n    if not creds or not creds.valid:\n        if creds and creds.expired and creds.refresh_token:\n            creds.refresh(Request())\n        else:\n            flow = InstalledAppFlow.from_client_secrets_file('credentials.json', SCOPES)\n            creds = flow.run_local_server(port=0)\n\n        # Save the access token in token.pickle file for the next run\n        with open('token.pickle', 'wb') as token:\n            pickle.dump(creds, token)\n\n    # Connect to the Gmail API\n    service = build('gmail', 'v1', credentials=creds)\n\n    # request a list of all the messages\n    result = service.users().messages().list(userId='me').execute()\n\n    # We can also pass maxResults to get any number of emails. Like this:\n    # result = service.users().messages().list(maxResults=200, userId='me').execute()\n    messages = result.get('messages')\n\n    # messages is a list of dictionaries where each dictionary contains a message id.\n\n    # iterate through all the messages\n    for msg in messages:\n        # Get the message from its id\n        txt = service.users().messages().get(userId='me', id=msg['id']).execute()\n\n        # Use try-except to avoid any Errors\n        try:\n            # Get value of 'payload' from dictionary 'txt'\n            payload = txt['payload']\n            headers = payload['headers']\n\n            # Look for Subject and Sender Email in the headers\n            for d in headers:\n                if d['name'] == 'Subject':\n                    subject = d['value']\n                if d['name'] == 'From':\n                    sender = d['value']\n\n            # The Body of the message is in Encrypted format. So, we have to decode it.\n            # Get the data and decode it with base 64 decoder.\n            parts = payload.get('parts')[0]\n            data = parts['body']['data']\n            data = data.replace("-","+").replace("_","/")\n            decoded_data = base64.b64decode(data)\n\n            # Now, the data obtained is in lxml. So, we will parse\n            # it with BeautifulSoup library\n            soup = BeautifulSoup(decoded_data , "lxml")\n            body = soup.body()\n\n            # Printing the subject, sender's email and message\n            print("Subject: ", subject)\n            print("From: ", sender)\n            print("Message: ", body)\n            print('\\n')\n        except:\n            pass\n\n\ngetEmails()\n
Run Code Online (Sandbox Code Playgroud)\n

我在 Google Console 中创建了一个项目,并为其提供了我的 http://localhost:8000/ 的重定向 uri

\n

如果有人知道如何解决它,我会很高兴
\n谢谢。

\n

DaI*_*mTo 7

重定向 uri 未命中匹配是我们在开始使用 Oauth2 进行开发时遇到的最常见错误之一。这实际上是您的配置错误。

错误消息上有一个链接,您可以单击该链接error details

在此输入图像描述

在此页面上,它将告诉您应用程序发送的重定向 uri。

在此输入图像描述

您需要获取该 uri 并将其添加到客户端下项目的 Google 云控制台中。

在此输入图像描述

该视频还将向您展示如何

Google OAuth2:如何修复redirect_uri_mismatch 错误。第 2 部分 服务器端 Web 应用程序。

安装的应用程序与网络应用程序

您现在拥有的代码旨在作为已安装的应用程序运行。因此,flow = InstalledAppFlow.from_client_secrets_file( CREDENTIALS, SCOPES) 它会在运行代码的计算机上打开授权同意屏幕。为了使此代码正常工作,您应该在谷歌开发者控制台上创建桌面凭据。如果您看到重定向 uri 未匹配错误,可能是因为您已经创建了 Web 应用程序凭据。

此代码并不意味着在 Web 服务器上运行,因为它会生成本地 Web 服务器。 creds = flow.run_local_server(port=0) 如果您打算在 Web 服务器 Web 服务器流上运行它,则需要不同的代码。

网络应用程序示例

我仍在玩这个,我需要弄清楚如何让它根据需要刷新访问令牌。应该通过以下方式完成。我只需要弄清楚如何测试何时需要刷新。

oauth2_client = oauth2.GoogleRefreshTokenClient(
    client_id, client_secret, refresh_token)
Run Code Online (Sandbox Code Playgroud)

到目前为止我所拥有的:

import os

import flask
from flask import Flask,redirect,render_template,url_for, request
app = Flask(__name__, template_folder='templates')

import google_auth_oauthlib.flow
import ssl
context = ssl.SSLContext()
context.load_cert_chain('C:\Development\FreeLance\GoogleSamples\Python\cert.pem', 'C:\Development\FreeLance\GoogleSamples\Python\key.pem')

from googleapiclient.discovery import build
import google_auth_oauthlib.flow

SCOPES = ['https://mail.google.com/']

REDIRECT_URI = 'https://127.0.0.1:5000/oauth2callback'

CREDENTIALS = 'C:\Development\FreeLance\GoogleSamples\Credentials\CredWebEverything.json'

def get_flow():

    # Initialize the flow using the client ID and secret downloaded earlier.
    flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
        CREDENTIALS,
        scopes= SCOPES,
    )
    # Indicate where the API server will redirect the user after the user completes
    # the authorization flow. The redirect URI is required.
    flow.redirect_uri = REDIRECT_URI

    return flow


def redirect_user():

    flow = get_flow()
    # Generate URL for request to Google's OAuth 2.0 server.
    # Use kwargs to set optional request parameters.
    authorization_url, state = flow.authorization_url(
        # Enable offline access so that you can refresh an access token without
        # re-prompting the user for permission. Recommended for web server apps.
        access_type='offline',
        # Enable incremental authorization. Recommended as a best practice.
        include_granted_scopes='false')

    return authorization_url, state

@app.route('/login')
def login():
    authorization_url, state = redirect_user()
    return flask.redirect(authorization_url)

@app.route('/')
def index():
    return render_template('index.html', title="Home Page")

@app.route('/oauth2callback')
def oauth2callback():
    flow = get_flow()
    auth_code = request.args['code']
    flow.fetch_token(code=auth_code)
    credentials = flow.credentials

    # Connect to the Gmail API
    service = build('gmail', 'v1', credentials=credentials)

    # request a list of all the messages
    result = service.users().messages().list(userId='me').execute()
    messages = result.get('messages')
    for msg in messages:
        print(msg['id'])

    # saving the credetials for later.
    with open('token.json', 'w') as token:
        token.write(credentials.to_json())

    return "", 201

if __name__ == '__main__':
    # Bind to PORT if defined, otherwise default to 5000.
    port = int(os.environ.get('PORT', 5000))
    app.run(host='0.0.0.0', port=port, ssl_context=context)
Run Code Online (Sandbox Code Playgroud)