You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@superset.apache.org by "ddhanabalan (via GitHub)" <gi...@apache.org> on 2023/09/28 10:13:09 UTC
[GitHub] [superset] ddhanabalan opened a new issue, #25443: Unable to complete url-redirection after OAuth authentication completion from OKTA
ddhanabalan opened a new issue, #25443:
URL: https://github.com/apache/superset/issues/25443
#### How to reproduce the bug
In the OKTA server, i have set the following configurations:
1. Created a default OKTA server and added this application
2. Set client-authentication type and created the clientid and clientsecret for this application.
3. Set grant-type as AuthorizationCode
4. Set Login-flow to "redirect to app to initiate login".
5. Added redirect-uri as : https://<superset-app-domain>/oauth-authorized/okta
I have configured the below code-snipped in superset_config.py.
```
from flask import redirect, g, flash, request
from flask_appbuilder.security.views import UserDBModelView,AuthDBView
from superset.security import SupersetSecurityManager
from flask_appbuilder.security.views import expose
from flask_appbuilder.security.manager import BaseSecurityManager
from flask_login import login_user, logout_user
from flask_appbuilder.security.manager import AUTH_OAUTH
from dotenv import load_dotenv
from typing import Optional
import os
import logging
import base64
logger = logging.getLogger()
load_dotenv()
# Superset specific config
ROW_LIMIT = 5000
SUPERSET_WORKERS = 1
SUPERSET_WEBSERVER_PORT = os.environ['PORT']
MAPBOX_API_KEY = os.getenv('MAPBOX_API_KEY')
SQLLAB_ASYNC_TIME_LIMIT_SEC = 300
SQLLAB_TIMEOUT = 300
SUPERSET_WEBSERVER_TIMEOUT = 300
PUBLIC_ROLE_LIKE = 'Gamma'
ENABLE_PROXY_FIX = True
# Flask App Builder configuration# Your App secret key
SECRET_KEY='Dj0aDlHmYJi/MFxJdw0d8XoNxhDPML8VF/VsTJ/ktb6x7NQNEACuwLha'
# The SQLAlchemy connection string to your database backend
SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL')
SQLALCHEMY_TRACK_MODIFICATIONS = True
# Flask-WTF flag for CSRF.
WTF_CSRF_ENABLED = CSRF_ENABLED = True
# ====== Start Okta Login ===========
AUTH_TYPE = AUTH_OAUTH
AUTH_USER_REGISTRATION = True # allow self-registration (login creates a user)
AUTH_USER_REGISTRATION_ROLE = 'Public'
AUTH_ROLE_ADMIN = 'Public'
AUTH_ROLE_PUBLIC = 'Public'
SESSION_COOKIE_SAMESITE=None
SESSION_COOKIE_HTTPONLY=True
OKTA_BASE_URL = os.getenv('OKTA_BASE_URL')
OKTA_KEY = os.getenv('OKTA_KEY')
OKTA_SECRET = os.getenv('OKTA_SECRET')
sencode = (OKTA_KEY + ':' + OKTA_SECRET).encode("ascii")
bencode = base64.b64encode(sencode)
base64_string = bencode.decode("ascii")
OAUTH_PROVIDERS = [{
'name':'okta',
'token_key': 'code', # Name of the token in the response of access_token_url
'icon':'fa-circle-o', # Icon for the provider
'remote_app': {
'client_id': OKTA_KEY, # Client Id (Identify Superset application)
'client_secret': OKTA_SECRET, # Secret for this Client Id (Identify Superset application)
'client_kwargs': {
'scope': 'read profile email openid groups'
},
'access_token_method': 'POST', # HTTP Method to call access_token_url
'api_base_url': OKTA_BASE_URL+'/oauth2/default/v1/',
'access_token_url': OKTA_BASE_URL + '/oauth2/default/v1/token',
'authorize_url': OKTA_BASE_URL + '/oauth2/default/v1/authorize',
'server_metadata_url': f'{OKTA_BASE_URL}/.well-known/oauth-authorization-server',
'jwks_uri': OKTA_BASE_URL + '/oauth2/default/v1/keys',
'access_token_headers':{ # Additional headers for calls to access_token_url
'Authorization': 'Basic ' + base64_string
}
}
}]
class CustomAuthDBView(AuthDBView):
login_template = 'appbuilder/general/security/login_db.html'
@expose('/login/', methods=['GET', 'POST'])
def login(self):
redirect_url = "https://<superset-app-domain>/superset/welcome"
if request.args.get('username') is not None:
user = self.appbuilder.sm.find_user(username=request.args.get('username'))
login_user(user, remember=False)
return redirect(redirect_url)
elif g.user is not None and g.user.is_authenticated():
return redirect(redirect_url)
else:
flash('Unable to auto login', 'warning')
return super(CustomAuthDBView,self).login()
class CustomSsoSecurityManager(SupersetSecurityManager):
authdbview = CustomAuthDBView
def oauth_user_info(self, provider, response=None):
logger.log('oauth2 provider: {0}'.format(provider))
logger.log('response: {0}'.format(response))
if provider == "okta":
me = self.appbuilder.sm.oauth_remotes[provider].get("userinfo")
data = me.json()
return {
"username": data.get("sub", ""),
"first_name": "",
"last_name": "",
"email": data.get("email", ""),
"role_keys": data.get("groups", []),
}
def auth_user_oauth(self, userinfo):
user = super(CustomSsoSecurityManager, self).auth_user_oauth(userinfo)
logger.debug(' Update <User: %s> role to %s', user.username)
self.update_user(user) # update user roles
return user
CUSTOM_SECURITY_MANAGER = CustomSsoSecurityManager
# ====== End Okta Login ============
```
After all these configurations, executing the below commands to configure and
run superset in Heroku.
1. superset db upgrade
2. superset fab create-admin
3. superset init
4. superset run
### Expected results
When clicked login, user is directed to OKTA sign-in page and
user is able to complete the authentication/authorization process and
user is redirected to superset welcome screen.
### Actual results
The redirect is getting stuck in the middle.
After authorization is complete, the app-redirect-url is getting stuck at
https://<superset-app-domain>/login/okta?next=
as there is no url parameter passed.
#### Screenshots

### Environment
- browser type and version: latest version of firefox/chrome/edge browser
- superset version: `2.0.1`
- python version: `3.8.16`
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org
Re: [I] Unable to complete url-redirection, redirection getting stuck after OAuth authentication completion from OKTA [superset]
Posted by "ddhanabalan (via GitHub)" <gi...@apache.org>.
ddhanabalan closed issue #25443: Unable to complete url-redirection, redirection getting stuck after OAuth authentication completion from OKTA
URL: https://github.com/apache/superset/issues/25443
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org
Re: [I] Unable to complete url-redirection, redirection getting stuck after OAuth authentication completion from OKTA [superset]
Posted by "ddhanabalan (via GitHub)" <gi...@apache.org>.
ddhanabalan commented on issue #25443:
URL: https://github.com/apache/superset/issues/25443#issuecomment-1746159420
The CustomSsoSecurityManager was not overridden. Replaced the OKTA code with this:
```
# ====== Start Okta Login ===========
ENABLE_PROXY_FIX = True
AUTH_TYPE = AUTH_OAUTH
AUTH_USER_REGISTRATION = True # allow self-registration (login creates a user)
AUTH_USER_REGISTRATION_ROLE = 'Public'
AUTH_ROLE_ADMIN = 'Public'
AUTH_ROLE_PUBLIC = 'Public'
SESSION_COOKIE_SAMESITE='None'
SESSION_COOKIE_HTTPONLY=False
SESSION_COOKIE_SECURE = True
OKTA_BASE_URL = get_env_variable('OKTA_BASE_URL')
OKTA_KEY = get_env_variable('OKTA_KEY')
OKTA_SECRET = get_env_variable('OKTA_SECRET')
sencode = (OKTA_KEY + ':' + OKTA_SECRET).encode("ascii")
bencode = base64.b64encode(sencode)
base64_string = bencode.decode("ascii")
OAUTH_PROVIDERS = [{
'name':'okta',
'token_key': 'access_token', # Name of the token in the response of access_token_url
'icon':'fa-circle-o', # Icon for the provider
'remote_app': {
'client_id': OKTA_KEY, # Client Id (Identify Superset application)
'client_secret': OKTA_SECRET, # Secret for this Client Id (Identify Superset application)
'client_kwargs': {
'scope': 'read profile email openid groups'
},
'access_token_method': 'POST', # HTTP Method to call access_token_url
'api_base_url': OKTA_BASE_URL+'/oauth2/default/v1/',
'access_token_url': OKTA_BASE_URL + '/oauth2/default/v1/token',
'authorize_url': OKTA_BASE_URL + '/oauth2/default/v1/authorize',
'server_metadata_url': f'{OKTA_BASE_URL}/.well-known/openid-configuration',
'jwks_uri': OKTA_BASE_URL + '/oauth2/default/v1/keys',
'access_token_headers':{ # Additional headers for calls to access_token_url
'Authorization': 'Basic ' + base64_string
}
}
}]
class CustomAuthOAuthView(AuthOAuthView):
@expose("/login/")
@expose("/login/<provider>")
@expose("/login/<provider>/<register>")
def login(self, provider: Optional[str] = None) -> WerkzeugResponse:
logger.debug("Provider: {0}".format(provider))
if g.user is not None and g.user.is_authenticated:
logger.debug("Already authenticated {0}".format(g.user))
return redirect(self.appbuilder.get_url_for_index)
if provider is None:
if len(self.appbuilder.sm.oauth_providers) > 1:
return self.render_template(
self.login_template,
providers=self.appbuilder.sm.oauth_providers,
title=self.title,
appbuilder=self.appbuilder,
)
else:
provider = self.appbuilder.sm.oauth_providers[0]["name"]
logger.debug("Going to call authorize for: {0}".format(provider))
state = jwt.encode(
request.args.to_dict(flat=False),
self.appbuilder.app.config["SECRET_KEY"],
algorithm="HS256",
)
try:
if provider == "okta":
return self.appbuilder.sm.oauth_remotes[provider].authorize_redirect(
redirect_uri=url_for(
".oauth_authorized",
provider=provider,
_external=True,
state=state,
)
)
else:
return self.appbuilder.sm.oauth_remotes[provider].authorize_redirect(
redirect_uri=url_for(
".oauth_authorized", provider=provider, _external=True
),
state=state.decode("ascii") if isinstance(state, bytes) else state,
)
except Exception as e:
logger.error("Error on OAuth authorize: {0}".format(e))
flash(as_unicode(self.invalid_login_message), "warning")
return redirect(self.appbuilder.get_url_for_index)
@expose("/oauth-authorized/okta")
def oauth_authorized(self, provider):
logger.debug("Authorized init")
resp = self.appbuilder.sm.oauth_remotes[provider].authorized_response()
if resp is None:
flash(u"You denied the request to sign in.", "warning")
return redirect("login")
logger.debug("OAUTH Authorized resp: {0}".format(resp))
# Retrieves specific user info from the provider
try:
self.appbuilder.sm.set_oauth_session(provider, resp)
userinfo = self.appbuilder.sm.oauth_user_info(provider, resp)
except Exception as e:
logger.error("Error returning OAuth user info: {0}".format(e))
user = None
else:
logger.debug("User info retrieved from {0}: {1}".format(provider, userinfo))
# User email is not whitelisted
if provider in self.appbuilder.sm.oauth_whitelists:
whitelist = self.appbuilder.sm.oauth_whitelists[provider]
allow = False
for e in whitelist:
if re.search(e, userinfo["email"]):
allow = True
break
if not allow:
flash(u"You are not authorized.", "warning")
return redirect("login")
else:
logger.debug("No whitelist for OAuth provider")
user = self.appbuilder.sm.auth_user_oauth(userinfo)
if user is None:
flash(as_unicode(self.invalid_login_message), "warning")
return redirect("login")
else:
login_user(user)
try:
state = jwt.decode(
request.args["code"],
self.appbuilder.app.config["SECRET_KEY"],
algorithms=["HS256"],
)
except jwt.InvalidTokenError:
raise Exception("State signature is not valid!")
try:
next_url = state["next"][0] or self.appbuilder.get_url_for_index
print("next_url: " + next_url)
if (len(next_url) <= 1):
next_url = "/superset/welcome/"
except (KeyError, IndexError):
next_url = self.appbuilder.get_url_for_index
print("next_url: " + next_url)
return redirect(next_url)
class CustomSsoSecurityManager(SupersetSecurityManager):
authoidview = CustomAuthOAuthView
def __init__(self, appbuilder):
super(CustomSsoSecurityManager, self).__init__(appbuilder)
def oauth_user_info(self, provider, response=None):
logger.debug('oauth2 provider: {0}'.format(provider))
logger.debug('response: {0}'.format(response))
if provider == "okta":
me = self.appbuilder.sm.oauth_remotes[provider].get("userinfo")
return {
"username": me.data.get("email", ""),
"first_name": "",
"last_name": "",
"email": me.data.get("email", ""),
"role_keys": me.data.get("groups", []),
}
def auth_user_oauth(self, userinfo):
user = super(CustomSsoSecurityManager, self).auth_user_oauth(userinfo)
if user == None:
logger.debug(' Update <User: %s> role to %s', userinfo.username)
self.update_user(userinfo) # update user roles
return user
SECURITY_MANAGER_CLASS = CustomSsoSecurityManager
# ====== End Okta Login ============
```
Guess its an older version of Flask-AppBuilder.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org
[GitHub] [superset] mdeshmu commented on issue #25443: Unable to complete url-redirection, redirection getting stuck after OAuth authentication completion from OKTA
Posted by "mdeshmu (via GitHub)" <gi...@apache.org>.
mdeshmu commented on issue #25443:
URL: https://github.com/apache/superset/issues/25443#issuecomment-1741941910
Any hints in the logs?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org
Re: [I] Unable to complete url-redirection, redirection getting stuck after OAuth authentication completion from OKTA [superset]
Posted by "vrychkov-repay (via GitHub)" <gi...@apache.org>.
vrychkov-repay commented on issue #25443:
URL: https://github.com/apache/superset/issues/25443#issuecomment-2298591814
@ddhanabalan, this may be related to a different way security manager is customized in Superset - https://github.com/apache/superset/blob/4.0.1/superset/initialization/__init__.py#L524-L539 - not like in classic FAB
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org