Skip to content

Instantly share code, notes, and snippets.

@brijeshb42
Last active September 25, 2020 20:16
Show Gist options
  • Star 19 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
  • Save brijeshb42/f4dcac5c8f4d4ab4a73a to your computer and use it in GitHub Desktop.
Save brijeshb42/f4dcac5c8f4d4ab4a73a to your computer and use it in GitHub Desktop.
import os
import json
import datetime
from flask import Flask, url_for, redirect, \
render_template, session, request
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.login import LoginManager, login_required, login_user, \
logout_user, current_user, UserMixin
from requests_oauthlib import OAuth2Session
from requests.exceptions import HTTPError
basedir = os.path.abspath(os.path.dirname(__file__))
"""App Configuration"""
class Auth:
"""Google Project Credentials"""
CLIENT_ID = ('688061596571-3c13n0uho6qe34hjqj2apincmqk86ddj'
'.apps.googleusercontent.com')
CLIENT_SECRET = 'JXf7Ic_jfCam1S7lBJalDyPZ'
REDIRECT_URI = 'https://localhost:5000/gCallback'
AUTH_URI = 'https://accounts.google.com/o/oauth2/auth'
TOKEN_URI = 'https://accounts.google.com/o/oauth2/token'
USER_INFO = 'https://www.googleapis.com/userinfo/v2/me'
SCOPE = ['profile', 'email']
class Config:
"""Base config"""
APP_NAME = "Test Google Login"
SECRET_KEY = os.environ.get("SECRET_KEY") or "somethingsecret"
class DevConfig(Config):
"""Dev config"""
DEBUG = True
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, "test.db")
class ProdConfig(Config):
"""Production config"""
DEBUG = False
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, "prod.db")
config = {
"dev": DevConfig,
"prod": ProdConfig,
"default": DevConfig
}
"""APP creation and configuration"""
app = Flask(__name__)
app.config.from_object(config['dev'])
db = SQLAlchemy(app)
login_manager = LoginManager(app)
login_manager.login_view = "login"
login_manager.session_protection = "strong"
""" DB Models """
class User(db.Model, UserMixin):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(100), unique=True, nullable=False)
name = db.Column(db.String(100), nullable=True)
avatar = db.Column(db.String(200))
tokens = db.Column(db.Text)
created_at = db.Column(db.DateTime, default=datetime.datetime.utcnow())
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
""" OAuth Session creation """
def get_google_auth(state=None, token=None):
if token:
return OAuth2Session(Auth.CLIENT_ID, token=token)
if state:
return OAuth2Session(
Auth.CLIENT_ID,
state=state,
redirect_uri=Auth.REDIRECT_URI)
oauth = OAuth2Session(
Auth.CLIENT_ID,
redirect_uri=Auth.REDIRECT_URI,
scope=Auth.SCOPE)
return oauth
@app.route('/')
@login_required
def index():
return render_template('index.html')
@app.route('/login')
def login():
if current_user.is_authenticated:
return redirect(url_for('index'))
google = get_google_auth()
auth_url, state = google.authorization_url(
Auth.AUTH_URI, access_type='offline')
session['oauth_state'] = state
return render_template('login.html', auth_url=auth_url)
@app.route('/gCallback')
def callback():
if current_user is not None and current_user.is_authenticated:
return redirect(url_for('index'))
if 'error' in request.args:
if request.args.get('error') == 'access_denied':
return 'You denied access.'
return 'Error encountered.'
if 'code' not in request.args and 'state' not in request.args:
return redirect(url_for('login'))
else:
google = get_google_auth(state=session['oauth_state'])
try:
token = google.fetch_token(
Auth.TOKEN_URI,
client_secret=Auth.CLIENT_SECRET,
authorization_response=request.url)
except HTTPError:
return 'HTTPError occurred.'
google = get_google_auth(token=token)
resp = google.get(Auth.USER_INFO)
if resp.status_code == 200:
user_data = resp.json()
email = user_data['email']
user = User.query.filter_by(email=email).first()
if user is None:
user = User()
user.email = email
user.name = user_data['name']
print(token)
user.tokens = json.dumps(token)
user.avatar = user_data['picture']
db.session.add(user)
db.session.commit()
login_user(user)
return redirect(url_for('index'))
return 'Could not fetch your information.'
@app.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('index'))
{%- if current_user.is_authenticated() -%}
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<form class="navbar-form navbar-left" role="search" action="/search">
<div class="form-group">
<input autofocus type="text" class="form-control" placeholder="Search" name="q">
</div>
<button type="submit" class="btn btn-default btn-sm">Search</button>
</form>
<ul class="nav navbar-nav">
<li><a href="#">Upload</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">{{current_user.name}}</a></li>
<li><a href="{{url_for('logout')}}"><img src="{{current_user.avatar}}?sz=20" width="20" height="20" alt="{{current_user.name}}">Logout</a></li>
</ul>
</div><!-- /.navbar-collapse -->
{%- else -%}
<a href="{{url_for('login')}}" class="btn btn-primary btn-block" style="padding: 15px 0;">Login</a>
{%- endif -%}
<a href="{{auth_url}}" class="btn btn-primary btn-block" style="padding: 15px 0;">Login with Google</a>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment