Google App Engine 烧瓶 SSL 和 OAuth2 问题

Posted

技术标签:

【中文标题】Google App Engine 烧瓶 SSL 和 OAuth2 问题【英文标题】:Google App Engine flask SSL and OAuth2 problems 【发布时间】:2018-08-10 19:24:38 【问题描述】:

我正在尝试在自定义域上使用 oauth2 身份验证在谷歌应用引擎 python 3 灵活环境上创建烧瓶 Web 应用程序。 因此,问题如下: 1) 我已将自定义域添加到我的项目中,并将 SSL 添加到该自定义域。在谷歌云控制台中,一切似乎都很好,但 SSL 没有在我的自定义域上显示/工作。 也许问题出在我的调度文件中?

dispatch:
    - url: 'mycustomdomain.com/'
      service: default

    - url: 'www.mycustomdomain.com/'
      service: default

2) 尽管https://[project-id].appspot.com 上有 SSL,但我无法登录。按“使用 Google 登录”后,我将重定向到 /authorize,在这里我选择要登录的帐户。之后重定向到 /oauth2callback,https 神秘地更改为 http,我无法登录,出现以下错误 InsecureTransportError: (insecure_transport) OAuth 2 MUST utilize https. Python 授权:

@app.route('/authorize')
def authorize():

    flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
        CLIENT_SECRETS_FILE, scopes=SCOPES)

    flow.redirect_uri = flask.url_for('oauth2callback', _external=True)

    authorization_url, state = flow.authorization_url(
        access_type='offline',
        include_granted_scopes='true')  

    flask.session['state'] = state
    return flask.redirect(authorization_url)

Python oauth2callback:

@app.route('/oauth2callback')
def oauth2callback():

    state = flask.session['state']

    flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
        CLIENT_SECRETS_FILE, scopes=SCOPES, state=state)
    flow.redirect_uri = flask.url_for('oauth2callback', _external=True)

    authorization_response = flask.request.url
    flow.fetch_token(authorization_response=authorization_response)

    credentials = flow.credentials

    flask.session['credentials'] = credentials_to_dict(credentials)
    session = flow.authorized_session()
    flask.session['username_output'] = session.get(
        'https://www.googleapis.com/userinfo/v2/me').json()

    return flask.redirect(flask.url_for('map'))

在本地测试时,我使用的是 os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1',并且在本地运行良好有什么建议吗??

解决方案 问题已解决 - 1)我忘记将 SSL 证书添加到域(托管域),这就是 SSL 不显示的原因。我知道,这是一个蹩脚的错误。 2)首先,我为flask强制使用SSLify,但这并没有解决问题,这是在以下行

authorization_response = flask.request.url

无论如何,这行代码给了我 http://,我试图将我能找到的每个方案都更改为 flask.url_for(_scheme='https') 中的 https,但这也无济于事,所以现在,我的解决方法是

authorization_response = authorization_response.replace('http', 'https')

我知道,这不是最好的解决方案,但它确实有效。

【问题讨论】:

有一个 Flask 库,您可以使用它来强制所有连接到 https。 github.com/GoogleCloudPlatform/flask-talisman 【参考方案1】:

我也遇到了这个问题,发现问题源于authorization_response = flask.request.url,因为该 URL 默认为 HTTP 而不是 HTTPS。

我的 hacky 解决方案是运行快速正则表达式替换并强制 URL 为 HTTPS:

import re
....
authorization_response = request.url
new_auth = re.sub(
    "http:",
    "https:",
    authorization_response
)
flow.fetch_new_token(new_auth)

当然有更好的方法来实现这一点,但它确实有效。

【讨论】:

【参考方案2】:

我遇到了这个错误,因为我在 gunicorn/flask 前面使用了 nginx

我通过添加修复它

proxy_set_header X-Forwarded-Proto $scheme;

到我的 nginx 配置,然后添加

from werkzeug.middleware.proxy_fix import ProxyFix

application.wsgi_app = ProxyFix(application.wsgi_app, x_proto=1)

到 gunicorn 调用的文件。

对于您在 GAE Python 3 Flex 环境中的具体问题,您需要配置 gunicorn 以执行相同的操作。

App Engine 在负载平衡器处终止 HTTPS 连接并将请求转发到您的应用程序。大多数应用程序不需要知道请求是否通过 HTTPS 发送,但需要此信息的应用程序应将 Gunicorn 配置为信任其 gunicorn.conf.py 中的 App Engine 代理:

forwarded_allow_ips = '*'
secure_scheme_headers = 'X-Forwarded-Proto': 'https'

Gunicorn 现在将确保 wsgi.url_scheme 到“https”,大多数 Web 框架将使用它来指示请求是安全的。如果您的 WSGI 服务器或框架不支持此功能,只需手动检查 X-Forwarded-Proto 标头的值。

https://cloud.google.com/appengine/docs/flexible/python/runtime#recommended_gunicorn_configuration

【讨论】:

以上是关于Google App Engine 烧瓶 SSL 和 OAuth2 问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 Google App Engine 时 SSL 证书无效和/或丢失

google-app-engine部署错误

带有 Let's Encrypt 的 Google App Engine SSL“无法插入”

Google App Engine Node.js 本地开发服务器是不是支持 SSL?

Google Cloud App Engine:如何在灵活的环境中提供 https

在 Google App Engine 上连接 python 后端和 vue.js 前端