Skip to content

Instantly share code, notes, and snippets.

@ashutoshkrris
Created March 24, 2021 07:57
Show Gist options
  • Select an option

  • Save ashutoshkrris/982ecef4ece02561dd4de8a978c13447 to your computer and use it in GitHub Desktop.

Select an option

Save ashutoshkrris/982ecef4ece02561dd4de8a978c13447 to your computer and use it in GitHub Desktop.
Flask Google Login
from Flask import Flask, redirect, request, url_for
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, current_user, login_user, logout_user, login_required
import json
import os
from oauthlib.oauth2 import WebApplicationClient
import requests
# Configuration
GOOGLE_CLIENT_ID = os.environ.get("GOOGLE_CLIENT_ID", None)
GOOGLE_CLIENT_SECRET = os.environ.get("GOOGLE_CLIENT_SECRET", None)
GOOGLE_DISCOVERY_URL = (
"https://accounts.google.com/.well-known/openid-configuration"
)
app = Flask(__name__)
app.secret_key = "i-am-very-secret"
app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///iread.db"
db = SQLAlchemy(app)
# User session management setup
# https://flask-login.readthedocs.io/en/latest
login_manager = LoginManager()
login_manager.init_app(app)
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), nullable=False)
email = db.Column(db.String(50), nullable=False)
profile_image = db.Column(db.String(500), nullable=True)
@app.route('/')
def index():
if current_user.is_authenticated:
return (
"<p>Hello, {}! You're logged in! Email: {}</p>"
"<div><p>Google Profile Picture:</p>"
'<img src="{}" alt="Google profile pic"></img></div>'
'<a class="button" href="/logout">Logout</a>'.format(
current_user.name, current_user.email, current_user.profile_pic
)
)
else:
return '<a class="button" href="/login">Google Login</a>'
def get_google_provider_cfg():
return requests.get(GOOGLE_DISCOVERY_URL).json()
@app.route('/login')
def login():
# Find out what URL to hit for Google login
google_provider_cfg = get_google_provider_cfg()
authorization_endpoint = google_provider_cfg["authorization_endpoint"]
# Use library to construct the request for Google login and provide
# scopes that let you retrieve user's profile from Google
request_uri = client.prepare_request_uri(
authorization_endpoint,
redirect_uri=request.base_url + "/callback",
scope=["openid", "email", "profile"],
)
return redirect(request_uri)
@app.route("/login/callback")
def callback():
# Get authorization code Google sent back to you
code = request.args.get("code")
# Find out what URL to hit to get tokens that allow you to ask for
# things on behalf of a user
google_provider_cfg = get_google_provider_cfg()
token_endpoint = google_provider_cfg["token_endpoint"]
# Prepare and send a request to get tokens! Yay tokens!
token_url, headers, body = client.prepare_token_request(
token_endpoint,
authorization_response=request.url,
redirect_url=request.base_url,
code=code
)
token_response = requests.post(
token_url,
headers=headers,
data=body,
auth=(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET),
)
# Parse the tokens!
client.parse_request_body_response(json.dumps(token_response.json()))
# Now that you have tokens (yay) let's find and hit the URL
# from Google that gives you the user's profile information,
# including their Google profile image and email
userinfo_endpoint = google_provider_cfg["userinfo_endpoint"]
uri, headers, body = client.add_token(userinfo_endpoint)
userinfo_response = requests.get(uri, headers=headers, data=body)
# You want to make sure their email is verified.
# The user authenticated with Google, authorized your
# app, and now you've verified their email through Google!
if userinfo_response.json().get("email_verified"):
users_email = userinfo_response.json()["email"]
picture = userinfo_response.json()["picture"]
users_name = userinfo_response.json()["given_name"]
else:
return "User email not available or not verified by Google.", 400
# Create a user in your db with the information provided
# by Google
# Doesn't exist? Add it to the database.
if not User.query.filter_by(email=username).first():
new_user = User(name=users_name, email=users_email, profile_image=picture)
db.session.add(new_user)
db.session.commit()
# Begin user session by logging the user in
user = User.query.filter_by(email=users_email).first()
login_user(user)
# Send user back to homepage
return redirect(url_for("index"))
@app.route("/logout")
@login_required
def logout():
logout_user()
return redirect(url_for("index"))
if __name__ == '__main__':
app.run(port=5000, debug=True)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment