Fix Github/Google oAuth

This commit is contained in:
Khanh Ngo 2018-08-19 15:29:50 +07:00
parent ada6f844ff
commit babf62bae0
No known key found for this signature in database
GPG Key ID: B9AE3BAF6D5A7B22
6 changed files with 118 additions and 104 deletions

View File

@ -3,7 +3,7 @@ from flask import Flask, request, session, redirect, url_for
from flask_login import LoginManager
from flask_sqlalchemy import SQLAlchemy as SA
from flask_migrate import Migrate
from flask_oauthlib.client import OAuth
# subclass SQLAlchemy to enable pool_pre_ping
class SQLAlchemy(SA):
@ -26,89 +26,13 @@ logging = logger('powerdns-admin', app.config['LOG_LEVEL'], app.config['LOG_FILE
login_manager = LoginManager()
login_manager.init_app(app)
db = SQLAlchemy(app)
migrate = Migrate(app, db) # used for flask-migrate
def enable_github_oauth(GITHUB_ENABLE):
if not GITHUB_ENABLE:
return None, None
from flask_oauthlib.client import OAuth
oauth = OAuth(app)
github = oauth.remote_app(
'github',
consumer_key=app.config['GITHUB_OAUTH_KEY'],
consumer_secret=app.config['GITHUB_OAUTH_SECRET'],
request_token_params={'scope': app.config['GITHUB_OAUTH_SCOPE']},
base_url=app.config['GITHUB_OAUTH_URL'], # API URL
request_token_url=None,
access_token_method='POST',
access_token_url=app.config['GITHUB_OAUTH_TOKEN'],
authorize_url=app.config['GITHUB_OAUTH_AUTHORIZE']
)
@app.route('/user/authorized')
def authorized():
session['github_oauthredir'] = url_for('.authorized', _external=True)
resp = github.authorized_response()
if resp is None:
return 'Access denied: reason=%s error=%s' % (
request.args['error'],
request.args['error_description']
)
session['github_token'] = (resp['access_token'], '')
return redirect(url_for('.login'))
@github.tokengetter
def get_github_oauth_token():
return session.get('github_token')
return oauth, github
oauth, github = enable_github_oauth(app.config.get('GITHUB_OAUTH_ENABLE'))
def enable_google_oauth(GOOGLE_ENABLE):
if not GOOGLE_ENABLE:
return None
from flask_oauthlib.client import OAuth
oauth = OAuth(app)
google = oauth.remote_app(
'google',
consumer_key=app.config['GOOGLE_OAUTH_CLIENT_ID'],
consumer_secret=app.config['GOOGLE_OAUTH_CLIENT_SECRET'],
request_token_params=app.config['GOOGLE_TOKEN_PARAMS'],
base_url=app.config['GOOGLE_BASE_URL'],
request_token_url=None,
access_token_method='POST',
access_token_url=app.config['GOOGLE_TOKEN_URL'],
authorize_url=app.config['GOOGLE_AUTHORIZE_URL'],
)
@app.route('/user/authorized')
def authorized():
resp = google.authorized_response()
if resp is None:
return 'Access denied: reason=%s error=%s' % (
request.args['error_reason'],
request.args['error_description']
)
session['google_token'] = (resp['access_token'], '')
return redirect(url_for('.login'))
@google.tokengetter
def get_google_oauth_token():
return session.get('google_token')
return google
google = enable_google_oauth(app.config.get('GOOGLE_OAUTH_ENABLE'))
from app import views, models
db = SQLAlchemy(app) # database
migrate = Migrate(app, db) # flask-migrate
oauth = OAuth(app) # oauth
if app.config.get('SAML_ENABLED') and app.config.get('SAML_ENCRYPT'):
from app.lib import certutil
if not certutil.check_certificate():
certutil.create_self_signed_cert()
from app import models, views

View File

@ -1805,7 +1805,6 @@ class Setting(db.Model):
'google_oauth_enabled': False,
'google_oauth_client_id':'',
'google_oauth_client_secret':'',
'google_redirect_uri': '/user/authorized',
'google_token_url': 'https://accounts.google.com/o/oauth2/token',
'google_token_params': {'scope': 'email profile'},
'google_authorize_url':'https://accounts.google.com/o/oauth2/auth',

79
app/oauth.py Normal file
View File

@ -0,0 +1,79 @@
from ast import literal_eval
from flask import request, session, redirect, url_for
from flask_oauthlib.client import OAuth
from app import app, oauth
from app.models import Setting
# TODO:
# - Replace Flask-OAuthlib by authlib
# - Fix flask-migrate issue with calling Setting() class during downgrade / upgrade
# - Fix github/google enabling (Currently need to reload the flask app)
def github_oauth():
if not Setting().get('github_oauth_enabled'):
return None
github = oauth.remote_app(
'github',
consumer_key = Setting().get('github_oauth_key'),
consumer_secret = Setting().get('github_oauth_secret'),
request_token_params = {'scope': Setting().get('github_oauth_scope')},
base_url = Setting().get('github_oauth_api_url'),
request_token_url = None,
access_token_method = 'POST',
access_token_url = Setting().get('github_oauth_token_url'),
authorize_url = Setting().get('github_oauth_authorize_url')
)
@app.route('/github/authorized')
def github_authorized():
session['github_oauthredir'] = url_for('.github_authorized', _external=True)
resp = github.authorized_response()
if resp is None:
return 'Access denied: reason=%s error=%s' % (
request.args['error'],
request.args['error_description']
)
session['github_token'] = (resp['access_token'], '')
return redirect(url_for('.login'))
@github.tokengetter
def get_github_oauth_token():
return session.get('github_token')
return github
def google_oauth():
if not Setting().get('google_oauth_enabled'):
return None
google = oauth.remote_app(
'google',
consumer_key=Setting().get('google_oauth_client_id'),
consumer_secret=Setting().get('google_oauth_client_secret'),
request_token_params=literal_eval(Setting().get('google_token_params')),
base_url=Setting().get('google_base_url'),
request_token_url=None,
access_token_method='POST',
access_token_url=Setting().get('google_token_url'),
authorize_url=Setting().get('google_authorize_url'),
)
@app.route('/google/authorized')
def google_authorized():
resp = google.authorized_response()
if resp is None:
return 'Access denied: reason=%s error=%s' % (
request.args['error_reason'],
request.args['error_description']
)
session['google_token'] = (resp['access_token'], '')
return redirect(url_for('.login'))
@google.tokengetter
def get_google_oauth_token():
return session.get('google_token')
return google

View File

@ -159,10 +159,6 @@
</fieldset>
<fieldset>
<legend>ADVANCE</legend>
<div class="form-group">
<label for="google_redirect_uri">Redirect URI</label>
<input type="text" class="form-control" name="google_redirect_uri" id="google_redirect_uri" placeholder="e.g. /user/authorized" value="{{ SETTING.get('google_redirect_uri') }}">
</div>
<div class="form-group">
<label for="google_token_url">Token URL</label>
<input type="text" class="form-control" name="google_token_url" id="google_token_url" placeholder="e.g. https://accounts.google.com/o/oauth2/token" value="{{ SETTING.get('google_token_url') }}">

View File

@ -18,8 +18,9 @@ from werkzeug import secure_filename
from werkzeug.security import gen_salt
from .models import User, Account, Domain, Record, Role, Server, History, Anonymous, Setting, DomainSetting, DomainTemplate, DomainTemplateRecord
from app import app, login_manager, github, google
from app import app, login_manager
from app.lib import utils
from app.oauth import github_oauth, google_oauth
from app.decorators import admin_role_required, can_access_domain, can_configure_dnssec
if app.config['SAML_ENABLED']:
@ -27,6 +28,8 @@ if app.config['SAML_ENABLED']:
from onelogin.saml2.utils import OneLogin_Saml2_Utils
logging = logger.getLogger(__name__)
google = google_oauth()
github = github_oauth()
# FILTERS
app.jinja_env.filters['display_record_name'] = utils.display_record_name
@ -147,16 +150,19 @@ def register():
@app.route('/google/login')
def google_login():
if not app.config.get('GOOGLE_OAUTH_ENABLE'):
if not Setting().get('google_oauth_enabled'):
return abort(400)
return google.authorize(callback=url_for('authorized', _external=True))
else:
return google.authorize(callback=url_for('google_authorized', _external=True))
@app.route('/github/login')
def github_login():
if not app.config.get('GITHUB_OAUTH_ENABLE'):
if not Setting().get('github_oauth_enabled'):
return abort(400)
return github.authorize(callback=url_for('authorized', _external=True))
else:
return github.authorize(callback=url_for('github_authorized', _external=True))
@app.route('/saml/login')
def saml_login():
@ -167,6 +173,7 @@ def saml_login():
redirect_url=OneLogin_Saml2_Utils.get_self_url(req) + url_for('saml_authorized')
return redirect(auth.login(return_to=redirect_url))
@app.route('/saml/metadata')
def saml_metadata():
if not app.config.get('SAML_ENABLED'):
@ -184,6 +191,7 @@ def saml_metadata():
resp = make_response(errors.join(', '), 500)
return resp
@app.route('/saml/authorized', methods=['GET', 'POST'])
def saml_authorized():
errors = []
@ -268,6 +276,7 @@ def saml_authorized():
else:
return render_template('errors/SAML.html', errors=errors)
@app.route('/login', methods=['GET', 'POST'])
@login_manager.unauthorized_handler
def login():
@ -302,14 +311,19 @@ def login():
return redirect(url_for('index'))
if 'github_token' in session:
me = github.get('user')
user_info = me.data
user = User.query.filter_by(username=user_info['name']).first()
me = github.get('user').data
github_username = me['login']
github_name = me['name']
github_email = me['email']
user = User.query.filter_by(username=github_username).first()
if not user:
# create user
user = User(username=user_info['name'],
user = User(username=github_username,
plain_text_password=None,
email=user_info['email'])
firstname=github_name,
lastname='',
email=github_email)
result = user.create_local_user()
if not result['status']:
@ -387,6 +401,7 @@ def login():
except Exception as e:
return render_template('register.html', error=e)
def clear_session():
session.pop('user_id', None)
session.pop('github_token', None)
@ -394,6 +409,7 @@ def clear_session():
session.clear()
logout_user()
@app.route('/logout')
def logout():
if app.config.get('SAML_ENABLED') and 'samlSessionIndex' in session and app.config.get('SAML_LOGOUT'):
@ -409,6 +425,7 @@ def logout():
clear_session()
return redirect(url_for('login'))
@app.route('/saml/sls')
def saml_logout():
req = utils.prepare_flask_request(request)
@ -426,6 +443,7 @@ def saml_logout():
else:
return render_template('errors/SAML.html', errors=errors)
@app.route('/dashboard', methods=['GET', 'POST'])
@login_required
def dashboard():
@ -1386,7 +1404,6 @@ def admin_setting_authentication():
Setting().set('google_oauth_enabled', True if request.form.get('google_oauth_enabled') else False)
Setting().set('google_oauth_client_id', request.form.get('google_oauth_client_id'))
Setting().set('google_oauth_client_secret', request.form.get('google_oauth_client_secret'))
Setting().set('google_redirect_uri', request.form.get('google_redirect_uri'))
Setting().set('google_token_url', request.form.get('google_token_url'))
Setting().set('google_token_params', request.form.get('google_token_params'))
Setting().set('google_authorize_url', request.form.get('google_authorize_url'))

View File

@ -59,11 +59,10 @@ def update_data():
{'id': 32, 'name': 'google_oauth_enabled', 'value': 'False', 'view': 'authentication'},
{'id': 33, 'name': 'google_oauth_client_id', 'value': '', 'view': 'authentication'},
{'id': 34, 'name': 'google_oauth_client_secret', 'value': '', 'view': 'authentication'},
{'id': 35, 'name': 'google_redirect_uri', 'value': '/user/authorized', 'view': 'authentication'},
{'id': 36, 'name': 'google_token_url', 'value': 'https://accounts.google.com/o/oauth2/token', 'view': 'authentication'},
{'id': 37, 'name': 'google_token_params', 'value': "{'scope': 'email profile'}", 'view': 'authentication'},
{'id': 38, 'name': 'google_authorize_url', 'value': 'https://accounts.google.com/o/oauth2/auth', 'view': 'authentication'},
{'id': 39, 'name': 'google_base_url', 'value': 'https://www.googleapis.com/oauth2/v1/', 'view': 'authentication'},
{'id': 35, 'name': 'google_token_url', 'value': 'https://accounts.google.com/o/oauth2/token', 'view': 'authentication'},
{'id': 36, 'name': 'google_token_params', 'value': "{'scope': 'email profile'}", 'view': 'authentication'},
{'id': 37, 'name': 'google_authorize_url', 'value': 'https://accounts.google.com/o/oauth2/auth', 'view': 'authentication'},
{'id': 38, 'name': 'google_base_url', 'value': 'https://www.googleapis.com/oauth2/v1/', 'view': 'authentication'},
]
)