As described in our previous blog about selecting an Analytics solution for Turbo Apps at Unvired, we decided to go ahead with Apache Superset as our analytics / dashboarding tool of choice for Unvired Turbo Apps. As a quick reminder, Unvired Turbo Apps is our low code application development platform that enables business users and citizen developers to build apps fast. However, to get Superset to work seamlessly with Turbo Apps, a few additional customizations were needed. This series of blogs seek to explain this in a little more detail in the hope that it could also be of use to others in leveraging this fantastic tool.
The Superset dashboards were expected to be embedded in the Turbo Apps Builder (aka Admin Portal) and allow Managers and Administrators to measure outcomes easily from the data collected (Inspection data, Work Permits, etc.). To make the process seamless for the user, the following had to be achieved either via extensions or configuration:
1. SSO – Single Sign-On. Users were already logged into the Turbo Apps and the same credentials had to be propagated to Superset.
2. Public access was a strict no, data access had to be limited based on roles. We also had to limit what Turbo App users could do with Superset based on roles.
3. Multi-tenancy was to be supported as the Turbo Apps is a predominantly cloud-based SaaS and customers used different tenants and data separation was to be carried into Superset.
4. Additional APIs to provision customers and users were required to be added to Superset.
5. While some standard dashboards were to be shipped to all customers, we also needed the ability to add customer-specific dashboards.
6. Embed the dashboards. Ability to switch dashboards. Import / Export dashboards across landscapes (Dev and Production).
The Superset documentation, issue tracker, blogs, and a number of posts from other users served as starting points for all the topics above, and a lot of the solutions articulated are built upon what the community has posted and is not Unvired/Turbo Apps specific or proprietary.
In this blog, let’s start out with the SSO implementation. The Turbo Apps suite uses JWT token-based authentication. The application has access to the token and our idea was to propagate this token to Superset when the dashboard was embedded. The embed as defined by Superset was to be done via an iFrame. It is therefore trivial to propagate the token via a token=xxxxx to the embed URL. The challenge was more to do with how to achieve the SSO as we didn’t want to ask users to register themselves in Superset but had to automate it.
The solution lies in the Flask Security framework based on which Superset is developed. A lot of blogs explain this but the most useful one for our purpose was: https://sairamkrish.medium.com/apache-superset-custom-authentication-and-integrate-with-other-micro-services-8217956273c1. The need was to develop a Custom Security Manager which could create the required new users or validate the existing ones based on the JWT token and then allow the user to log in or simply redirect unauthenticated or disallowed users to the login page.
The steps involved are:
1. Create a Custom Authentication module:
a. Validate the JWT token
b. If the user has access rights to Superset dashboards, find the user and proceed with login. If user not found create the user and log in.
c. Return error in all other cases.
2. Plugin the authentication module so that Superset can utilize it.
Note: We will revisit this module once the roles and multi-tenancy are developed. The login module needs to be enhanced to achieve that.
Creating the Authentication module (some sample/reference code is available in the referenced blog).
login_template = 'appbuilder/general/security/login_db.html'
@expose('/login/', methods=['GET', 'POST'])
if request.args.get('apitoken') is not None:
# Validate this against the system issuing the token
# User exists?
user = self.appbuilder.sm.find_user(username=usernamefromjwt)
# redirect to the passed it dashboard url – configure a slug for each dashboard and use that
# Return to login screen
In the superset_config.py (where the SQLALCHEMY_DATABASE_URI and other values have been configured) add the following:
from yourcustommodule import CustomSecurityManager
CUSTOM_SECURITY_MANAGER = CustomSecurityManager
When the iframe embedded Superset URL now tries to load the dashboard (identified via the slug), the control is transferred to your custom login module. The custom login module now verifies the JWT token and then creates the required user or directly logs in the user if found. The dashboard now renders seamlessly and the user is not required to perform any additional authentication.
Note: The user can always “escape” from the “fullscreen” dashboard and end up in the Superset UI. We will later see how to use Roles to limit what these users can do in Superset.
Also Read: Unvired turbo forms app reloaded
CORS – Here I come!
Given that the URL for Superset is embedded in another containing application, you can get hit by CORS depending on what actual URLs you use. For e.g. subpaths of your main web application URL will not have issues but other URLs might. The Superset documentation has hints on how to configure CORS to get over this issue here: https://superset.apache.org/docs/installation/networking-settings#cors
In the next blog, I will articulate how to leverage roles to restrict users in what access they have within Superset.