Login with Google Sign on Dash app

I have no problem getting a Flask app to use Google Sign In through flask-dance , but I’m unable to make it work with a Dash app. Basically, I expose the Flask server as the user guide says and then use the server to implement the Google Sign In functionality as I do in a Flask app. Yet, when I start the app, I get to the Dash app without getting the Google Sign In page. I copy my (edited) code below. Any help would be more than appreciated:

import dash
import dash_core_components as dcc
import dash_html_components as html

from flask import Flask, redirect, url_for
from flask_dance.contrib.google import make_google_blueprint, google

app = dash.Dash()
server = app.server

blueprint = make_google_blueprint(
    client_id='*****',
    client_secret='*****',
    scope=["profile", "email"]
)

server.register_blueprint(blueprint, url_prefix="/login")

@server.route("/")
def index():
    if not google.authorized:
        return redirect(url_for("google.login"))
    resp = google.get("/oauth2/v2/userinfo")
    assert resp.ok, resp.text
    return "You are {email} on Google".format(email=resp.json()["email"])


app.layout = html.Div(children=[
    html.H1('Hello Dash')
])

if __name__ == '__main__':
    server.run(host="0.0.0.0", port=80)
2 Likes

Lucas Chapin has a working solution here: https://github.com/lucaschapin/dash-google-auth

1 Like

I have also implemented the same in my MLM Software Websites

Nice help team. loved it

Hi, I tried using dash-google-auth but I’m getting an error. I did all of the steps from the README.md file and replaced the variables for client ID and client secret with real values like this:

app.server.config["GOOGLE_OAUTH_CLIENT_ID"] = os.environ.get("client-id-here")
        app.server.config["GOOGLE_OAUTH_CLIENT_SECRET"] = os.environ.get("client-secret-here")

However, when I ran python app.py and opened “localhost:5000” in my browser I got the following error:

401. That’s an error.

Error: invalid_client

The OAuth client was not found.

Request Details
response_type=code
client_id=None
redirect_uri=http://localhost:5000/login/google/authorized
scope=profile email
state=1kPQ9gCwR3EkGbXV5LdnPLu1TgQEpn
access_type=offline
approval_prompt=force
That’s all we know.

I put the following into the “Authorized redirect URIs” field: http://localhost:5000/login/google/authorized

Any idea why I might be getting this error? Thanks.

I recently played around with using flask-dance myself. I wish I had come across Lucas’ repo sooner – I will probably rebase my auth class around his.

If you take a look at what google’s oauth is reporting, the OAuth request isn’t formed properly because client_id=None.

That means that for some reason this line isn’t taking:
app.server.config["GOOGLE_OAUTH_CLIENT_ID"] = os.environ.get("client-id-here")

Maybe try hard-coding the client id and secret and try again? Good luck-

One thing I noted about dash-google-auth: it doesn’t attempt to handle invalid tokens (basically any error types from oauthlib.oauth2.rfc6749.errors). In this case, the client will continue to receive 403 unauthorized until the token is deleted (session clear).

You need to remove “os.environ.get” and just put the ID and secret in, as follows:

app.server.config["GOOGLE_OAUTH_CLIENT_ID"] = "client-id-here"
    app.server.config["GOOGLE_OAUTH_CLIENT_SECRET"] = "client-secret-here"

I was trying to add multiple routes for the page, but everytime I try to route it to different page, it always come back to the index page layout. any idea why it is happening?

This is because the url_base_pathname of you dash app is set to the index:

app = Dash(
    __name__,
    server=server,
    url_base_pathname='/',
)

Change this to ‘/mydashapp/’ or something
Then create a route in flask to acces the dash app:

@server.route("/mydashapp")
def MyDashApp():
    return app.index()

FYI

I was facing this error: Warning: Scope has changed from “…googleapis.com/auth/userinfo.profile …googleapis.com/auth/userinfo.email” to “openid …googleapis.com/auth/userinfo.profile …googleapis.com/auth/userinfo.email”.

To solve it add additional_scopes=[“openid”] in the google_oauth.py file as such:

def __init__(self, app, authorized_emails, additional_scopes=["openid"]):
        super(GoogleOAuth, self).__init__(app)
        google_bp = make_google_blueprint(
            scope=[
                "https://www.googleapis.com/auth/userinfo.email",
                "https://www.googleapis.com/auth/userinfo.profile",
            ] + (additional_scopes if additional_scopes else []),
            offline=True,
            reprompt_consent=True,
        )
        app.server.register_blueprint(google_bp, url_prefix="/login")
        self.authorized_emails = authorized_emails

Hi,

Did any one worked out how to achieve user credentials after logging in?

I want to be able to use the credentials to authenticate with Google APIs.

Thanks in advance

It was a great help for my MLM software company.

updated December 2021 for aws this GitHub - lchapo/dash-google-auth: (Deprecated) Dash Extension for Google OAuth

from dash_google_auth import GoogleOAuth

app = dash.Dash(name=name,
title=‘namel’,
assets_folder=“static”,
assets_url_path=“static”
)

application = app.server

application.secret_key = os.environ.get(“FLASK_SECRET_KEY”, “supersekrit”)
application.config[“GOOGLE_OAUTH_CLIENT_ID”] = “xxxxxxxx”
application.config[“GOOGLE_OAUTH_CLIENT_SECRET”] = “xxxxxxxxx”

os.environ[‘OAUTHLIB_INSECURE_TRANSPORT’] = ‘1’
os.environ[‘OAUTHLIB_RELAX_TOKEN_SCOPE’] = ‘1’

query=’’‘xxx’’’
df=run_query(query)
email = df.user.to_list()

auth = GoogleOAuth(
app,
email,
)

@application.route("/")
def MyDashApp():
return app.index()

The GitHub states that this package might not work with Dash versions >= 1.0. Have you tested this?

I know this is fastidious, but maybe switching to Authlib will help. They are up to date and integrate Flask Client. They have a template on google authentication. They have the most stars on github if you search for python oauth
Basically configure dash app without server (server=False), configure your flask server with authentication through Authlib, then dash_app.init_app(server), and finally require login on each route that leads to the dash app.

Tutorial to build the server

Plus this trick to force authentication on dash apps to run inside a loop on all your dash apps connected to the flask server :

for view_func in app_flask.view_functions:
    if view_func.startswith(app_dash.url_base_pathname):
        app_flask.view_functions[view_func] = login_required(app_flask.view_functions[view_func])
2 Likes