Created
March 24, 2021 07:57
-
-
Save ashutoshkrris/982ecef4ece02561dd4de8a978c13447 to your computer and use it in GitHub Desktop.
Flask Google Login
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| | |
| 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