diff --git a/redash/authentication/__init__.py b/redash/authentication/__init__.py index 225732c959..193f3ba242 100644 --- a/redash/authentication/__init__.py +++ b/redash/authentication/__init__.py @@ -4,7 +4,7 @@ import hmac import time import logging - +from authlib.flask.client import OAuth from flask import redirect, request, jsonify, url_for from redash import models, settings @@ -12,6 +12,8 @@ from redash.tasks import record_event login_manager = LoginManager() +oauth = OAuth() + logger = logging.getLogger('authentication') @@ -156,9 +158,10 @@ def logout_and_redirect_to_index(): def setup_authentication(app): - from redash.authentication import google_oauth, saml_auth, remote_user_auth, ldap_auth + from redash.authentication import google_oauth, saml_auth, remote_user_auth, ldap_auth, mobifun_auth login_manager.init_app(app) + oauth.init_app(app) login_manager.anonymous_user = models.AnonymousUser app.secret_key = settings.COOKIE_SECRET @@ -166,6 +169,7 @@ def setup_authentication(app): app.register_blueprint(saml_auth.blueprint) app.register_blueprint(remote_user_auth.blueprint) app.register_blueprint(ldap_auth.blueprint) + app.register_blueprint(mobifun_auth.blueprint) user_logged_in.connect(log_user_logged_in) diff --git a/redash/authentication/mobifun_auth.py b/redash/authentication/mobifun_auth.py new file mode 100644 index 0000000000..ff1db48e8b --- /dev/null +++ b/redash/authentication/mobifun_auth.py @@ -0,0 +1,77 @@ +import logging +from flask import redirect, url_for, Blueprint, flash, request, session +from redash.authentication import oauth + + +from redash import models, settings +from redash.authentication import create_and_login_user, logout_and_redirect_to_index +from redash.authentication.org_resolving import current_org + +logger = logging.getLogger('mobifun_auth') + +blueprint = Blueprint('mobifun_auth', __name__) + + +def fetch_remote_token(): + return session['auth_token'] + + +def register_remote_app(): + oauth.register('redash', + client_id='WAm_WlYsp-YlN6_3gxWWG2WY-FWLHrm1', + client_secret='qDItuJDJxiXEJU-kKDJDo03rjb7QKQtX', + access_token_url='https://portal.mobifun365.com/oauth-2/token', + access_token_params=None, + refresh_token_url=None, + authorize_url='https://portal.mobifun365.com/oauth-2/auth', + api_base_url='https://portal.mobifun365.com/', + client_kwargs={'scope': 'profile'}, + fetch_token=fetch_remote_token, + ) + return oauth.redash + + +@blueprint.route('//oauth/redash', endpoint="authorize_org") +def org_login(org_slug): + session['org_slug'] = current_org.slug + return redirect(url_for(".authorize", next=request.args.get('next', None))) + + +@blueprint.route('/oauth/redash', endpoint="authorize") +def login(): + redirect_uri = url_for('.callback', _external=True) + return register_remote_app().authorize_redirect(redirect_uri) + + +@blueprint.route('/oauth/redash_callback', endpoint="callback") +def authorized(): + access_token = register_remote_app().authorize_access_token() + + if access_token is None: + logger.warning("Access token missing in call back request.") + flash("Validation error. Please retry.") + return redirect(url_for('redash.login')) + + session['auth_token'] = access_token + session['auth_token']['token_type'] = 'Bearer' + session['auth_token']['expires_in'] = 3600 + + return redirect(url_for('.profile', _external=True)) + + +@blueprint.route('/oauth/get_profile', endpoint="profile") +def app_profile(): + resp = register_remote_app().get('oauth-2/resource') + profile = resp.json() + + picture_url = "%s?sz=40" % profile['picture'] + user = create_and_login_user(current_org, profile['name'], profile['email'], picture_url) + if user is None: + return logout_and_redirect_to_index() + + # next_path = request.args.get('state') or url_for("redash.index", org_slug=org.slug) + next_path = request.args.get('state') or url_for("redash.index") + + return redirect(next_path) + + diff --git a/redash/templates/invite.html b/redash/templates/invite.html index 21705c79a4..4be0fa5227 100644 --- a/redash/templates/invite.html +++ b/redash/templates/invite.html @@ -28,6 +28,11 @@ {% endif %} + + + Login with Mobifun Account + + {% if show_saml_login %} SAML Login {% endif %} diff --git a/redash/templates/login.html b/redash/templates/login.html index 36e112e65e..79c9312ce3 100644 --- a/redash/templates/login.html +++ b/redash/templates/login.html @@ -20,6 +20,11 @@ {% endif %} + + + Login with Mobifun Account + + {% if show_saml_login %} SAML Login {% endif %} diff --git a/requirements.txt b/requirements.txt index 7d6dcd7354..6eb9d8fa1f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -45,9 +45,10 @@ pystache==0.5.4 parsedatetime==2.1 cryptography==2.0.2 simplejson==3.10.0 -ua-parser==0.7.3 +ua-parser==0.7.3 user-agents==1.1.0 python-geoip-geolite2==2015.303 # Uncomment the requirement for ldap3 if using ldap. # It is not included by default because of the GPL license conflict. # ldap3==2.2.4 +Authlib==0.7