From 3f6b7e24567d088196726fc387edb815a103e497 Mon Sep 17 00:00:00 2001 From: lindner-tj Date: Thu, 11 Jul 2024 21:10:23 +0200 Subject: [PATCH] docs: Added Keycloak auth configuration (#29487) Co-authored-by: Sam Firke --- .../configuration/configuring-superset.mdx | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/docs/docs/configuration/configuring-superset.mdx b/docs/docs/configuration/configuring-superset.mdx index e21fe5d6dc727..a433bdc02d7ee 100644 --- a/docs/docs/configuration/configuring-superset.mdx +++ b/docs/docs/configuration/configuring-superset.mdx @@ -321,7 +321,103 @@ CUSTOM_SECURITY_MANAGER = CustomSsoSecurityManager } ] ``` +### Keycloak-Specific Configuration using Flask-OIDC +If you are using Keycloak as OpenID Connect 1.0 Provider, the above configuration based on [`Authlib`](https://authlib.org/) might not work. In this case using [`Flask-OIDC`](https://https://pypi.org/project/flask-oidc/) is a viable option. +Make sure the pip package [`Flask-OIDC`](https://https://pypi.org/project/flask-oidc/) is installed on the webserver. This was succesfully tested using version 2.2.0. This package requires [`Flask-OpenID`](https://pypi.org/project/Flask-OpenID/) as a dependency. + +The following code defines a new security manager. Add it to a new file named `keycloak_security_manager.py`, placed in the same directory as your `superset_config.py` file. +```python +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 +from flask import ( + redirect, + request +) +import logging + +class OIDCSecurityManager(SupersetSecurityManager): + + def __init__(self, appbuilder): + super(OIDCSecurityManager, self).__init__(appbuilder) + if self.auth_type == AUTH_OID: + self.oid = OpenIDConnect(self.appbuilder.get_app) + self.authoidview = AuthOIDCView + +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)) +``` +Then add to your `superset_config.py` file: +```python +from keycloak_security_manager import OIDCSecurityManager +from flask_appbuilder.security.manager import AUTH_OID, AUTH_REMOTE_USER, AUTH_DB, AUTH_LDAP, AUTH_OAUTH +import os + +AUTH_TYPE = AUTH_OID +SECRET_KEY: 'SomethingNotEntirelySecret' +OIDC_CLIENT_SECRETS = '/path/to/client_secret.json' +OIDC_ID_TOKEN_COOKIE_SECURE = False +OIDC_OPENID_REALM: '' +OIDC_INTROSPECTION_AUTH_METHOD: 'client_secret_post' +CUSTOM_SECURITY_MANAGER = OIDCSecurityManager + +# Will allow user self registration, allowing to create Flask users from Authorized User +AUTH_USER_REGISTRATION = True + +# The default user self registration role +AUTH_USER_REGISTRATION_ROLE = 'Public' +``` +Store your client-specific OpenID information in a file called `client_secret.json`. Create this file in the same directory as `superset_config.py`: +```json +{ + "": { + "issuer": "https:///realms/", + "auth_uri": "https:///realms//protocol/openid-connect/auth", + "client_id": "https://", + "client_secret": "", + "redirect_uris": [ + "https:///oauth-authorized/" + ], + "userinfo_uri": "https:///realms//protocol/openid-connect/userinfo", + "token_uri": "https:///realms//protocol/openid-connect/token", + "token_introspection_uri": "https:///realms//protocol/openid-connect/token/introspect" + } +} +``` ## LDAP Authentication FAB supports authenticating user credentials against an LDAP server.