You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask程序部署至Google Cloud Shell时遭遇Google OAuth访问被阻止问题

问题:Google Cloud Shell部署Flask Google OAuth认证失败

本地运行基于Flask的Google OAuth认证程序时,能正常弹出浏览器完成Google账号认证;但部署到Google Cloud Shell后,点击登录链接出现「Access blocked: This app’s request is invalid」错误,无法完成认证并展示用户信息。

程序代码(app.py)

# copied from https://github.com/piyush-singhal/oauth-python/blob/main/app.py
# this seems the simplest way to authenicate with Google 
# developed on local box and works well.  It pops a browser window open and lets me pick my Google account on my browser
# 
# deploy to Google Shell in the GCP
# I get the expected screen
#   Example of Google Login in Python Flask Application
#   You are not logged in, Click on the below link to sign in with google.
# I click the link and then i get the dreaded 
#   "Access blocked: This app’s request is invalid"
# Any help you can offer would be appreciated.
#
# here is my debug log (with my client-id channged to protect me)
# start the logging.debug
# Hello  line 74
# Hello  line 76
 # * Debugger is active!
 # * Debugger PIN: 127-742-122
# Hello  line 78
# Hello  line 80
# Hello  line 81  Google.base_url    == https://www.googleapis.com/
# Hello  line 82  user_info_endpoint == /oauth2/v2/userinfo
# 127.0.0.1 - - [15/Jul/2024 11:41:41] "GET /?authuser=0 HTTP/1.1" 200 -
# Hello  line 89
# Hello  line 91 my_url_for-->/login/google
# 127.0.0.1 - - [15/Jul/2024 11:42:30] "GET /login HTTP/1.1" 302 -
# client_id = 0000000000000-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com
# Generated new state V18oHjswxgqJML9VgmF7ujpaiLi6KD.
# state = V18oHjswxgqJML9VgmF7ujpaiLi6KD
# redirect URL = https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=0000000000000-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com&redirect_uri=http%3A%2F%2F127.0.0.1%3A5000%2Flogin%2Fgoogle%2Fauthorized&scope=profile+email&state=V18oHjswxgqJML9VgmF7ujpaiLi6KD&prompt=consent


import os
import sys
from flask import Flask, render_template, redirect, url_for
from flask_dance.contrib.google import make_google_blueprint, google
import logging
import json
import json as json_module

app = Flask(__name__)

# Configuration
with open('./credentials.json', 'r') as file:
    json = json.load(file)
client_id     = json['installed']['client_id']
client_secret = json['installed']['client_secret']
secret_key    = os.environ.get("SECRET_KEY") or os.urandom(24)

logging.basicConfig(stream=sys.stdout, level=logging.DEBUG, format='%(message)s')

print("start the logging.debug")
logging.debug("Hello  line 52")

app.config['DEBUG'] = True
app.config['SECRET_KEY'] = secret_key

logging.debug("Hello  line 57")

os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE'] = '1'

blueprint = make_google_blueprint(
    client_id=client_id,
    client_secret=client_secret,
    reprompt_consent=True,
    scope=["profile", "email"]
)
app.register_blueprint(blueprint, url_prefix="/login")

@app.route("/")
def index():
    google_data = None
    user_info_endpoint = '/oauth2/v2/userinfo'
    logging.debug("Hello  line 74")
    if google.authorized:
        logging.debug("Hello  line 76")
        google_data = google.get(user_info_endpoint).json()
        logging.debug("Hello  line 78")

    logging.debug("Hello  line 80")
    logging.debug("Hello  line 81  Google.base_url    == " + google.base_url)
    logging.debug("Hello  line 82  user_info_endpoint == " + user_info_endpoint)
    return render_template('index.j2',
                           google_data=google_data,
                           fetch_url=google.base_url + user_info_endpoint)

@app.route('/login')
def login():
    logging.debug("Hello  line 89")
    my_url_for=url_for('google.login')
    logging.debug("Hello  line 91 my_url_for-->" + my_url_for )
    return redirect(my_url_for)
    #return redirect('/login/google')  #this works

if __name__ == "__main__":
    app.run()

模板文件(index.j2)

<!doctype html>
<html class="no-js" lang="">

<head>
  <title>Google Oauth 2.0 Login for python Flask application</title>
  <link rel="icon" href="/favicon.ico" type="image/x-icon">
</head>

<body>
  <h3>Example of Google Login in Python Flask Application</h3>
  {% if not google_data %}
    <p style="color:#333;">You are not logged in, Click on the below link to sign in with google.</p>
    <a href="/login" class="google-btn">
      <div class="google-icon-wrapper">
        <img class="google-icon" src="https://upload.wikimedia.org/wikipedia/commons/c/c1/Google_%22G%22_logo.svg"/>
      </div>
      <p class="btn-text"><b>Sign in with google</b></p>
    </a>
  {% else %}
    <p>Hi {{ google_data.name }}, [<strong>{{ google_data.email }}</strong>]. You have logged in successfully from your Google Account. Check your below details.</p>
  {% if google_data is not none %}
    <div class="detail">
      <p style="font-size: 15px; padding-bottom: 10px;">User info fetched from <strong>{{ fetch_url }}</strong></p>
      <table border='1'>
      {% for key, value in google_data.items() %}
        <tr><td>{{ key }}</td> <td><strong>{{ value }}</strong></td></tr>
      {% endfor %}
      </table>
    </div>
    <div> <img src="{{ google_data.picture }}" alt="User Picture">    </div>
  {% endif %}
  {% endif %}

</html>

调试日志

start the logging.debug
Hello  line 74
Hello  line 76
 * Debugger is active!
 * Debugger PIN: 127-742-122
Hello  line 78
Hello  line 80
Hello  line 81  Google.base_url    == https://www.googleapis.com/
Hello  line 82  user_info_endpoint == /oauth2/v2/userinfo
127.0.0.1 - - [15/Jul/2024 11:41:41] "GET /?authuser=0 HTTP/1.1" 200 -
Hello  line 89
Hello  line 91 my_url_for-->/login/google
127.0.0.1 - - [15/Jul/2024 11:42:30] "GET /login HTTP/1.1" 302 -
client_id = 0000000000000-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com
Generated new state V18oHjswxgqJML9VgmF7ujpaiLi6KD.
state = V18oHjswxgqJML9VgmF7ujpaiLi6KD
redirect URL = https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=0000000000000-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com&redirect_uri=http%3A%2F%2F127.0.0.1%3A5000%2Flogin%2Fgoogle%2Fauthorized&scope=profile+email&state=V18oHjswxgqJML9VgmF7ujpaiLi6KD&prompt=consent

问题原因及解决方案

核心问题分析

从调试日志里的redirect_uri=http%3A%2F%2F127.0.0.1%3A5000%2Flogin%2Fgoogle%2Fauthorized可以看出,程序在Cloud Shell中仍使用本地回调地址,但Cloud Shell提供的是公网可访问的URL(类似https://xxxx-xxxx-xxxx-xxxx.cloudshell.dev),Google OAuth不允许未在凭据中配置的回调地址,因此触发错误。另外,当前使用的是installed类型的OAuth凭据,这类凭据仅适用于本地桌面应用,部署到Web环境需要使用Web应用类型的凭据。

解决方案步骤

  1. 创建Web类型的OAuth凭据

    • 进入Google Cloud控制台的API和服务→凭据页面
    • 删除原有的「桌面应用」类型凭据,新建「Web应用」类型凭据
    • 在「已获授权的重定向URI」中添加Cloud Shell的公网回调地址,格式为https://[你的Cloud Shell公网域名]/login/google/authorized
    • 下载新的credentials.json,替换Cloud Shell中的文件
  2. 修改Flask应用配置,适配Cloud Shell的公网地址
    Cloud Shell运行Flask时,需要绑定0.0.0.0并指定端口,同时设置正确的回调地址。修改make_google_blueprint的配置,手动指定redirect_uri:

    # 获取Cloud Shell的公网域名,Cloud Shell会自动设置该环境变量
    import os
    cloud_shell_domain = os.environ.get("CLOUDSHELL_HOST")
    redirect_uri = f"https://{cloud_shell_domain}/login/google/authorized"
    
    blueprint = make_google_blueprint(
        client_id=client_id,
        client_secret=client_secret,
        reprompt_consent=True,
        scope=["profile", "email"],
        redirect_uri=redirect_uri
    )
    

    同时修改启动命令,让Flask监听所有地址:

    if __name__ == "__main__":
        app.run(host='0.0.0.0', port=5000)
    
  3. 确保环境变量配置正确
    保留OAUTHLIB_INSECURE_TRANSPORT=1(Cloud Shell的公网地址是HTTPS,可按需去掉),OAUTHLIB_RELAX_TOKEN_SCOPE=1可保留。

验证步骤

  • 在Cloud Shell中启动应用,访问提供的公网URL
  • 点击登录链接,此时回调地址已配置为Cloud Shell的公网地址,Google OAuth会正常跳转并完成认证

内容的提问来源于stack exchange,提问作者user23991531

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 01:07:01