diff --git a/docker/.env b/docker/.env index 25bdac0ab7fa..f8ae8aeec10e 100644 --- a/docker/.env +++ b/docker/.env @@ -51,3 +51,9 @@ SUPERSET_LOAD_EXAMPLES=yes CYPRESS_CONFIG=false SUPERSET_PORT=8088 MAPBOX_API_KEY='' + +OKTA_BASE_URL='' +OKTA_CLIENT_ID='' +OKTA_CLIENT_SECRET='' + +SSO_USER_REGISTRATION_ROLE=Admin \ No newline at end of file diff --git a/docker/custom_sso_security_manager.py b/docker/custom_sso_security_manager.py new file mode 100644 index 000000000000..d987954192d5 --- /dev/null +++ b/docker/custom_sso_security_manager.py @@ -0,0 +1,25 @@ +import os +from superset.security import SupersetSecurityManager + +class CustomSsoSecurityManager(SupersetSecurityManager): + """ + The CustomSsoSecurityManager class extends the SupersetSecurityManager class. + """ + def oauth_user_info(self, provider, response=None): + if provider == 'okta': + user_info = response.get("userinfo") + me = self.appbuilder.sm.oauth_remotes[provider].parse_id_token( + response, user_info["nonce"]) + first_name, last_name = me["name"].split(" ", 1) + return { + 'name': me['name'], + 'email': me['email'], + 'id': me['email'], + 'username': me['email'], + 'first_name': first_name, + 'last_name': last_name, + } + + def sync_roles(self): + self.add_role(os.getenv("SSO_USER_REGISTRATION_ROLE")) + return super().sync_roles() \ No newline at end of file diff --git a/docker/pythonpath_dev/superset_config.py b/docker/pythonpath_dev/superset_config.py index 005cc600ae1b..96af9dc2dc92 100644 --- a/docker/pythonpath_dev/superset_config.py +++ b/docker/pythonpath_dev/superset_config.py @@ -25,6 +25,9 @@ from celery.schedules import crontab from flask_caching.backends.filesystemcache import FileSystemCache +from flask_appbuilder.security.manager import AUTH_OAUTH +from custom_sso_security_manager import CustomSsoSecurityManager + logger = logging.getLogger() @@ -113,3 +116,32 @@ class CeleryConfig: ) except ImportError: logger.info("Using default Docker config...") + + +AUTH_TYPE = AUTH_OAUTH +CUSTOM_SECURITY_MANAGER = CustomSsoSecurityManager + +AUTH_USER_REGISTRATION = True +AUTH_USER_REGISTRATION_ROLE = os.getenv("SSO_USER_REGISTRATION_ROLE") +AUTH_ROLE_ADMIN = "Admin" + +OKTA_BASE_URL = os.getenv("OKTA_BASE_URL") +OAUTH_PROVIDERS = [ + { + "name": "okta", + "token_key": "access_token", + "icon": "fa-circle-o", + "remote_app": { + "client_id": os.getenv("OKTA_CLIENT_ID"), + "client_secret": os.getenv("OKTA_CLIENT_SECRET"), + "client_kwargs": {"scope": "openid profile email"}, + "access_token_method": "POST", + "api_base_url": f"{OKTA_BASE_URL}/oauth2/v1/", + "access_token_url": f"{OKTA_BASE_URL}/oauth2/v1/token", + "authorize_url": f"{OKTA_BASE_URL}/oauth2/v1/authorize", + "server_metadata_url": f"{OKTA_BASE_URL}/.well-known/openid-configuration", + 'request_token_url': None, + }, + }, +] + diff --git a/requirements/base.txt b/requirements/base.txt index 98d2a8094eee..6f143d539232 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -380,3 +380,5 @@ zipp==3.15.0 # The following packages are considered to be unsafe in a requirements file: # setuptools +Authlib==1.3.0 +Flask-AppBuilder==4.4.1 \ No newline at end of file