mirror of
https://github.com/getredash/redash.git
synced 2025-12-19 17:37:19 -05:00
Add support for Google OAuth Scheme Override (#7178)
* Added support for Google Oauth Scheme Override (through environment variable) * Refactoring * Refactoring * Applied formatting * Refactoring * Refactoring * Updated comment for `GOOGLE_OAUTH_SCHEME_OVERRIDE` variable * Updated comment for `GOOGLE_OAUTH_SCHEME_OVERRIDE` variable * Removed duplication of url_for function --------- Co-authored-by: kostiantyn-dementiev-op <kostiantyn.dementiev@observepoint.com>
This commit is contained in:
committed by
GitHub
parent
3f781d262b
commit
5ae1f70d9e
@@ -4,7 +4,7 @@ import requests
|
|||||||
from authlib.integrations.flask_client import OAuth
|
from authlib.integrations.flask_client import OAuth
|
||||||
from flask import Blueprint, flash, redirect, request, session, url_for
|
from flask import Blueprint, flash, redirect, request, session, url_for
|
||||||
|
|
||||||
from redash import models
|
from redash import models, settings
|
||||||
from redash.authentication import (
|
from redash.authentication import (
|
||||||
create_and_login_user,
|
create_and_login_user,
|
||||||
get_next_path,
|
get_next_path,
|
||||||
@@ -29,22 +29,8 @@ def verify_profile(org, profile):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def create_google_oauth_blueprint(app):
|
def get_user_profile(access_token, logger):
|
||||||
oauth = OAuth(app)
|
headers = {"Authorization": f"OAuth {access_token}"}
|
||||||
|
|
||||||
logger = logging.getLogger("google_oauth")
|
|
||||||
blueprint = Blueprint("google_oauth", __name__)
|
|
||||||
|
|
||||||
CONF_URL = "https://accounts.google.com/.well-known/openid-configuration"
|
|
||||||
oauth = OAuth(app)
|
|
||||||
oauth.register(
|
|
||||||
name="google",
|
|
||||||
server_metadata_url=CONF_URL,
|
|
||||||
client_kwargs={"scope": "openid email profile"},
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_user_profile(access_token):
|
|
||||||
headers = {"Authorization": "OAuth {}".format(access_token)}
|
|
||||||
response = requests.get("https://www.googleapis.com/oauth2/v1/userinfo", headers=headers)
|
response = requests.get("https://www.googleapis.com/oauth2/v1/userinfo", headers=headers)
|
||||||
|
|
||||||
if response.status_code == 401:
|
if response.status_code == 401:
|
||||||
@@ -53,6 +39,44 @@ def create_google_oauth_blueprint(app):
|
|||||||
|
|
||||||
return response.json()
|
return response.json()
|
||||||
|
|
||||||
|
|
||||||
|
def build_redirect_uri():
|
||||||
|
scheme = settings.GOOGLE_OAUTH_SCHEME_OVERRIDE or None
|
||||||
|
return url_for(".callback", _external=True, _scheme=scheme)
|
||||||
|
|
||||||
|
|
||||||
|
def build_next_path(org_slug=None):
|
||||||
|
next_path = request.args.get("next")
|
||||||
|
if not next_path:
|
||||||
|
if org_slug is None:
|
||||||
|
org_slug = session.get("org_slug")
|
||||||
|
|
||||||
|
scheme = None
|
||||||
|
if settings.GOOGLE_OAUTH_SCHEME_OVERRIDE:
|
||||||
|
scheme = settings.GOOGLE_OAUTH_SCHEME_OVERRIDE
|
||||||
|
|
||||||
|
next_path = url_for(
|
||||||
|
"redash.index",
|
||||||
|
org_slug=org_slug,
|
||||||
|
_external=True,
|
||||||
|
_scheme=scheme,
|
||||||
|
)
|
||||||
|
return next_path
|
||||||
|
|
||||||
|
|
||||||
|
def create_google_oauth_blueprint(app):
|
||||||
|
oauth = OAuth(app)
|
||||||
|
|
||||||
|
logger = logging.getLogger("google_oauth")
|
||||||
|
blueprint = Blueprint("google_oauth", __name__)
|
||||||
|
|
||||||
|
CONF_URL = "https://accounts.google.com/.well-known/openid-configuration"
|
||||||
|
oauth.register(
|
||||||
|
name="google",
|
||||||
|
server_metadata_url=CONF_URL,
|
||||||
|
client_kwargs={"scope": "openid email profile"},
|
||||||
|
)
|
||||||
|
|
||||||
@blueprint.route("/<org_slug>/oauth/google", endpoint="authorize_org")
|
@blueprint.route("/<org_slug>/oauth/google", endpoint="authorize_org")
|
||||||
def org_login(org_slug):
|
def org_login(org_slug):
|
||||||
session["org_slug"] = current_org.slug
|
session["org_slug"] = current_org.slug
|
||||||
@@ -60,9 +84,9 @@ def create_google_oauth_blueprint(app):
|
|||||||
|
|
||||||
@blueprint.route("/oauth/google", endpoint="authorize")
|
@blueprint.route("/oauth/google", endpoint="authorize")
|
||||||
def login():
|
def login():
|
||||||
redirect_uri = url_for(".callback", _external=True)
|
redirect_uri = build_redirect_uri()
|
||||||
|
|
||||||
next_path = request.args.get("next", url_for("redash.index", org_slug=session.get("org_slug")))
|
next_path = build_next_path()
|
||||||
logger.debug("Callback url: %s", redirect_uri)
|
logger.debug("Callback url: %s", redirect_uri)
|
||||||
logger.debug("Next is: %s", next_path)
|
logger.debug("Next is: %s", next_path)
|
||||||
|
|
||||||
@@ -86,7 +110,7 @@ def create_google_oauth_blueprint(app):
|
|||||||
flash("Validation error. Please retry.")
|
flash("Validation error. Please retry.")
|
||||||
return redirect(url_for("redash.login"))
|
return redirect(url_for("redash.login"))
|
||||||
|
|
||||||
profile = get_user_profile(access_token)
|
profile = get_user_profile(access_token, logger)
|
||||||
if profile is None:
|
if profile is None:
|
||||||
flash("Validation error. Please retry.")
|
flash("Validation error. Please retry.")
|
||||||
return redirect(url_for("redash.login"))
|
return redirect(url_for("redash.login"))
|
||||||
@@ -110,7 +134,9 @@ def create_google_oauth_blueprint(app):
|
|||||||
if user is None:
|
if user is None:
|
||||||
return logout_and_redirect_to_index()
|
return logout_and_redirect_to_index()
|
||||||
|
|
||||||
unsafe_next_path = session.get("next_url") or url_for("redash.index", org_slug=org.slug)
|
unsafe_next_path = session.get("next_url")
|
||||||
|
if not unsafe_next_path:
|
||||||
|
unsafe_next_path = build_next_path(org.slug)
|
||||||
next_path = get_next_path(unsafe_next_path)
|
next_path = get_next_path(unsafe_next_path)
|
||||||
|
|
||||||
return redirect(next_path)
|
return redirect(next_path)
|
||||||
|
|||||||
@@ -136,6 +136,13 @@ FEATURE_POLICY = os.environ.get("REDASH_FEATURE_POLICY", "")
|
|||||||
|
|
||||||
MULTI_ORG = parse_boolean(os.environ.get("REDASH_MULTI_ORG", "false"))
|
MULTI_ORG = parse_boolean(os.environ.get("REDASH_MULTI_ORG", "false"))
|
||||||
|
|
||||||
|
# If Redash is behind a proxy it might sometimes receive a X-Forwarded-Proto of HTTP
|
||||||
|
# even if your actual Redash URL scheme is HTTPS. This will cause Flask to build
|
||||||
|
# the OAuth redirect URL incorrectly thus failing auth. This is especially common if
|
||||||
|
# you're behind a SSL/TCP configured AWS ELB or similar.
|
||||||
|
# This setting will force the URL scheme.
|
||||||
|
GOOGLE_OAUTH_SCHEME_OVERRIDE = os.environ.get("REDASH_GOOGLE_OAUTH_SCHEME_OVERRIDE", "")
|
||||||
|
|
||||||
GOOGLE_CLIENT_ID = os.environ.get("REDASH_GOOGLE_CLIENT_ID", "")
|
GOOGLE_CLIENT_ID = os.environ.get("REDASH_GOOGLE_CLIENT_ID", "")
|
||||||
GOOGLE_CLIENT_SECRET = os.environ.get("REDASH_GOOGLE_CLIENT_SECRET", "")
|
GOOGLE_CLIENT_SECRET = os.environ.get("REDASH_GOOGLE_CLIENT_SECRET", "")
|
||||||
GOOGLE_OAUTH_ENABLED = bool(GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET)
|
GOOGLE_OAUTH_ENABLED = bool(GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET)
|
||||||
|
|||||||
Reference in New Issue
Block a user