+ {% with messages = get_flashed_messages() %}
+ {% if messages %}
+ {% for message in messages %}
+
{{ message }}
+ {% endfor %}
+ {% endif %}
+ {% endwith %}
{% if show_google_openid %}
diff --git a/redash/controllers.py b/redash/controllers.py
index 6ba4737cb5..7c845445ef 100644
--- a/redash/controllers.py
+++ b/redash/controllers.py
@@ -12,7 +12,7 @@
import logging
from flask import render_template, send_from_directory, make_response, request, jsonify, redirect, \
- session, url_for, current_app
+ session, url_for, current_app, flash
from flask.ext.restful import Resource, abort
from flask_login import current_user, login_user, logout_user, login_required
import sqlparse
@@ -80,7 +80,7 @@ def login():
login_user(user, remember=remember)
return redirect(request.args.get('next') or '/')
except models.User.DoesNotExist:
- pass
+ flash("Wrong username or password.")
return render_template("login.html",
name=settings.NAME,
diff --git a/redash/google_oauth.py b/redash/google_oauth.py
index b73ccdb9a8..72300ec945 100644
--- a/redash/google_oauth.py
+++ b/redash/google_oauth.py
@@ -1,25 +1,25 @@
import logging
from flask.ext.login import login_user
import requests
-from flask import redirect, url_for, Blueprint
+from flask import redirect, url_for, Blueprint, flash
from flask_oauth import OAuth
from redash import models, settings
logger = logging.getLogger('google_oauth')
oauth = OAuth()
-request_token_params = {'scope': 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile', 'response_type': 'code'}
-if settings.GOOGLE_APPS_DOMAIN:
- request_token_params['hd'] = settings.GOOGLE_APPS_DOMAIN
-else:
+if not settings.GOOGLE_APPS_DOMAIN:
logger.warning("No Google Apps domain defined, all Google accounts allowed.")
google = oauth.remote_app('google',
base_url='https://www.google.com/accounts/',
authorize_url='https://accounts.google.com/o/oauth2/auth',
request_token_url=None,
- request_token_params=request_token_params,
+ request_token_params={
+ 'scope': 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile',
+ 'response_type': 'code'
+ },
access_token_url='https://accounts.google.com/o/oauth2/token',
access_token_method='POST',
access_token_params={'grant_type': 'authorization_code'},
@@ -31,7 +31,7 @@
def get_user_profile(access_token):
- headers = {'Authorization': 'OAuth '+access_token}
+ headers = {'Authorization': 'OAuth {}'.format(access_token)}
response = requests.get('https://www.googleapis.com/oauth2/v1/userinfo', headers=headers)
if response.status_code == 401:
@@ -41,9 +41,17 @@ def get_user_profile(access_token):
return response.json()
+def verify_profile(profile):
+ if not settings.GOOGLE_APPS_DOMAIN:
+ return True
+
+ domain = profile['email'].split('@')[-1]
+ return domain in settings.GOOGLE_APPS_DOMAIN
+
+
def create_and_login_user(name, email):
try:
- user_object = models.User.get(models.User.email == email)
+ user_object = models.User.get_by_email(email)
if user_object.name != name:
logger.debug("Updating user name (%r -> %r)", user_object.name, name)
user_object.name = name
@@ -70,10 +78,17 @@ def authorized(resp):
if access_token is None:
logger.warning("Access token missing in call back request.")
+ flash("Validation error. Please retry.")
return redirect(url_for('login'))
profile = get_user_profile(access_token)
if profile is None:
+ flash("Validation error. Please retry.")
+ return redirect(url_for('login'))
+
+ if not verify_profile(profile):
+ logger.warning("User tried to login with unauthorized domain name: %s", profile['email'])
+ flash("Your Google Apps domain name isn't allowed.")
return redirect(url_for('login'))
create_and_login_user(profile['name'], profile['email'])
diff --git a/redash/settings.py b/redash/settings.py
index 4cb0366d62..2bef79cda1 100644
--- a/redash/settings.py
+++ b/redash/settings.py
@@ -32,6 +32,10 @@ def array_from_string(str):
return array
+def set_from_string(str):
+ return set(array_from_string(str))
+
+
def parse_boolean(str):
return json.loads(str.lower())
@@ -60,7 +64,7 @@ def parse_boolean(str):
# Google Apps domain to allow access from; any user with email in this Google Apps will be allowed
# access
-GOOGLE_APPS_DOMAIN = os.environ.get("REDASH_GOOGLE_APPS_DOMAIN", "")
+GOOGLE_APPS_DOMAIN = set_from_string(os.environ.get("REDASH_GOOGLE_APPS_DOMAIN", ""))
GOOGLE_CLIENT_ID = os.environ.get("REDASH_GOOGLE_CLIENT_ID", "")
GOOGLE_CLIENT_SECRET = os.environ.get("REDASH_GOOGLE_CLIENT_SECRET", "")