Mr Baumgarten

Computer Science teacher and self confessed geek

Using Google API to authenticate uses in Flask


pip install -r requirements.txt

Where your requirements.txt contains...



from flask_session import Session               ## pip install Flask-Session
import google.oauth2.credentials                ## Used by Google OAuth
import google_auth_oauthlib.flow                ## Used by Google OAuth
from googleapiclient.discovery import build     ## Used by Google OAuth

Global code

  • Ensure your sessions system is up and running. The following example just uses the local filesystem instead of a database
app = Flask(__name__)
app.config['SECRET_KEY'] = 'esdirolftjg rdsklthjrm,gme jkm2mw,3 werkj hswedf kdsjkh'
app.config['SESSION_TYPE'] = "filesystem"
app.config['SESSION_FILE_DIR'] = os.path.join(app.root_path, "sessions")
app.config['SESSION_FILE_THRESHOLD'] = 1000
  • Set the location of your client_secrets.json file and your Google Scopes

A list of the various scopes is available at

The client_secrets.json file should not be in your project folder. This is generally considered insecure practice. It is also recommended to not hardcode the location of your secrets file, but to set it via an environment variable.

CLIENT_SECRETS_FILE = '../client_secret.json' # ... OR ...
CLIENT_SECRETS_FILE = os.environ['client_secrets']
SCOPES = ['',

Setting environment variables

Via nginx

location / {
    uwsgi_param     CLIENT_SECRETS_FILE     '/folder/folder/client_secrets.json';


  • Add to /etc/environment (note: a reboot will be required)


def main():
    if "credentials" not in session:    ## If not logged in
        return redirect("authorize")    ## Start the login process
    elif "user" in session:             ## If we are logged in
                                        ## Return a customised index page
        return render_template("index.html", person=session['user']['name'])
    else:                               ## Else
        return send_file("index.html")  ## This should never be reached?

## Used by Google OAuth
def credentials_to_dict(credentials):
    return {'token': credentials.token,
            'refresh_token': credentials.refresh_token,
            'token_uri': credentials.token_uri,
            'client_id': credentials.client_id,
            'client_secret': credentials.client_secret,
            'scopes': credentials.scopes,
            'id_token': credentials.id_token}

## Used by Google OAuth
def login():
    if "credentials" not in session:
        return redirect("authorize")
        return redirect("/")

## Used by Google OAuth
def authorize():
    # Intiiate login request
    flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(CLIENT_SECRETS_FILE, scopes=SCOPES)
    flow.redirect_uri = url_for('oauth2callback', _external=True)
    authorization_url, state = flow.authorization_url(access_type='offline', include_granted_scopes='true')
    return redirect(authorization_url)

## Used by Google OAuth
def oauth2callback():
    # Receive an authorisation code from google
    flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(CLIENT_SECRETS_FILE, scopes=SCOPES)
    flow.redirect_uri = url_for('oauth2callback', _external=True)
    authorization_response = request.url
    # Use authorisation code to request credentials from Google
    credentials = flow.credentials
    session['credentials'] = credentials_to_dict(credentials)
    # Use the credentials to obtain user information and save it to the session
    oauth2_client = build('oauth2','v2',credentials=credentials)
    user_info= oauth2_client.userinfo().get().execute()
    session['user'] = user_info
    # Return to main page
    return redirect(url_for('/'))

While developing...

  • Set OS environment variable OAUTHLIB_INSECURE_TRANSPORT to 1 so Google will allow http
  • Set the parameter debug=True
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'"", port=8080, debug=True)

Session data

An example of the content that will be loaded into session['user] by the above process is...

    'email':        '',
    'family_name':  'Baumgarten',
    'given_name':   'Paul',
    'id':           '00000000000000000000',
    'locale':       'en-GB',
    'name':         'Paul Baumgarten',
    'picture':      '',
    'verified_email': True

See also