Apache Superset Integration with Keycloak

As you all know that Apache Superset is one of the most popular platform provided by Apache for data exploration and visualization. It helps to create different representations of data i.e. to create charts, graphs, etc.. With simple SQL query we can create dashboards for different systems, it also provides widgets to integrate those visualizations in our application.

Keycloak is also one of the most popular open source authentication provider. It can be integrated with any OIDC provider with minimal to no code writing efforts.

By default superset uses its own authentication mechanism, but most of the applications use Keycloak for authentication and in that case to use Superset, we must change its authentication mechanism and integrate it with Keycloak.

In this article, I am going to explain the entire process of Superset and Keycloak integration

Pre-requisites

You should know, how to setup Keycloak. In case, if you don’t, you can refer this article.

Procedure

Step 1: Download and setup Keycloak.

Step 2: Download Apache Superset from its repository. (In case, if code structure changes in future, I am also mentioning commit link here)

Step 3: We are going to integrate Keycloak with OIDC methodology. So that you can use this same procedure to integrate any OIDC provider with Superset. For that we need to add flask-oidc dependency in Superset and to do so, we need to add below line at line number 31 in Dockerfile-dev:

RUN cd /app \
&& pip install -e . \
&& pip install -r requirements/docker.txt \
&& pip install flask-oidc==1.4.0 \
&& pip install -r requirements/requirements-local.txt || true

Note: Only Bold line need to be added in Dockerfile-dev

Step 4: Go to docker/pythonpath_dev and create client_secret.json. We need to write below content in that file.

{
"web": {
"realm_public_key": "<REALM_PUBLIC_KEY>",
"issuer": "http://<KEYCLOAK_IP_PORT>/auth/realms/<REALM_NAME>",
"auth_uri": "http://<KEYCLOAK_IP_PORT>/auth/realms/<REALM_NAME>/protocol/openid-connect/auth",
"client_id": "<CLIENT_ID>",
"client_secret": "<CLIENT_SECRET>",
"userinfo_uri": "http://<KEYCLOAK_IP_PORT>/auth/realms/<REALM_NAME>/protocol/openid-connect/userinfo",
"token_uri": "http://<KEYCLOAK_IP_PORT>/auth/realms/<REALM_NAME>/protocol/openid-connect/token",
"token_introspection_uri": "http://<KEYCLOAK_IP_PORT>/auth/realms/<REALM_NAME>/protocol/openid-connect/token/introspect"
}
}

Above details(Realm name, public key, client id, client secret) you can get from Keycloak.

Step 5: Superset maintain its own table of users and whenever any new user logs in from Keycloak, its entry has to be there in Superset db and to make that possible we need to write a function which will make an entry of new user in Superset db.

Create a new file in the same folder and name it as Security.py and paste below code there:

from flask import redirect, request
from flask_appbuilder.security.manager import AUTH_OID
from superset.security import SupersetSecurityManager
from flask_oidc import OpenIDConnect
from flask_appbuilder.security.views import AuthOIDView
from flask_login import login_user
from urllib.parse import quote
from flask_appbuilder.views import ModelView, SimpleFormView, expose
import logging
class AuthOIDCView(AuthOIDView):
@expose('/login/', methods=['GET', 'POST'])
def login(self, flag=True):
sm = self.appbuilder.sm
oidc = sm.oid
@self.appbuilder.sm.oid.require_login
def handle_login():
user = sm.auth_user_oid(oidc.user_getfield('email'))
if user is None:
info = oidc.user_getinfo(['preferred_username', 'given_name', 'family_name', 'email'])
user = sm.add_user(info.get('preferred_username'), info.get('given_name'), info.get('family_name'), info.get('email'), sm.find_role('Gamma'))
login_user(user, remember=False)
return redirect(self.appbuilder.get_url_for_index)
return handle_login()
@expose('/logout/', methods=['GET', 'POST'])
def logout(self):
oidc = self.appbuilder.sm.oid
oidc.logout()
super(AuthOIDCView, self).logout()
redirect_url = request.url_root.strip('/') + self.appbuilder.get_url_for_login
return redirect(oidc.client_secrets.get('issuer') + '/protocol/openid-connect/logout?redirect_uri=' + quote(redirect_url))
class OIDCSecurityManager(SupersetSecurityManager):
authoidview = AuthOIDCView
def __init__(self,appbuilder):
super(OIDCSecurityManager, self).__init__(appbuilder)
if self.auth_type == AUTH_OID:
self.oid = OpenIDConnect(self.appbuilder.get_app)

If you look at the above code, we have extended AuthOIDView and SupersetSecurityManager. We also written a function called handle_login which will make an entry in Superset db, whenever a new user logs in. (Reference: stackoverflow answer)

Step 6: We need to make one last change in superset_config.py. We need to add below line in this file:

from security import OIDCSecurityManager
from flask_appbuilder.security.manager import AUTH_OID
curr = os.path.abspath(os.getcwd())AUTH_TYPE = AUTH_OID
OIDC_CLIENT_SECRETS = curr + '/pythonpath/client_secret.json'
OIDC_ID_TOKEN_COOKIE_SECURE = False
OIDC_REQUIRE_VERIFIED_EMAIL = False
AUTH_USER_REGISTRATION = True
AUTH_USER_REGISTRATION_ROLE = 'Gamma'
CUSTOM_SECURITY_MANAGER = OIDCSecurityManager

Step 8: Once all these changes are done. We need to build the docker image once. You can use following command to build the image.

docker build -t <image_name> .

Step 9: Now in docker-compose.yml replace below line

x-superset-image: &superset-image apache/superset:latest-dev

with

x-superset-image: &superset-image <image_name>

Step 10: Run the application using below command:

docker-compose up

Now open your browser and hit the Superset URL. You should get redirected to Keycloak login page and after adding proper creds, you will be reverted back to Superset.

Happy Coding….!!!

--

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Buffer Overflow to Run Root Shell

Acing CKAD Exam in a week

Connecting to Google BigQuery from Information Designer Tool (IDT)

Git Stash — When and How to Use

My Android Development Learning Path

IOEX Biweekly Report: Aug 24th — Sep 6th

Automated canary releasing with Jenkins on DC/OS: Part 2

Horizontally scaling writes with Redis Clusters

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Akash Suryawanshi

Akash Suryawanshi

More from Medium

Enable LDAP Authentication in Airflow

Airflow: Create Custom Operator from MySQL to PostgreSQL

Installing Airflow locally on Windows with WSL and Astro CLI (quickest setup ever)

How to create a custom Airflow sensor?