This is an automated email from the ASF dual-hosted git repository.

sfirke pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 3f6b7e2456 docs: Added Keycloak auth configuration (#29487)
3f6b7e2456 is described below

commit 3f6b7e24567d088196726fc387edb815a103e497
Author: lindner-tj <[email protected]>
AuthorDate: Thu Jul 11 21:10:23 2024 +0200

    docs: Added Keycloak auth configuration (#29487)
    
    Co-authored-by: Sam Firke <[email protected]>
---
 docs/docs/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 e21fe5d6dc..a433bdc02d 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: '<myRealm>'
+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
+{
+    "<myOpenIDProvider>": {
+        "issuer": "https://<myKeycloakDomain>/realms/<myRealm>",
+        "auth_uri": 
"https://<myKeycloakDomain>/realms/<myRealm>/protocol/openid-connect/auth",
+        "client_id": "https://<myKeycloakDomain>",
+        "client_secret": "<myClientSecret>",
+        "redirect_uris": [
+            "https://<SupersetWebserver>/oauth-authorized/<myOpenIDProvider>"
+  ],
+        "userinfo_uri": 
"https://<myKeycloakDomain>/realms/<myRealm>/protocol/openid-connect/userinfo",
+        "token_uri": 
"https://<myKeycloakDomain>/realms/<myRealm>/protocol/openid-connect/token",
+        "token_introspection_uri": 
"https://<myKeycloakDomain>/realms/<myRealm>/protocol/openid-connect/token/introspect"
+  }
+}
+```
 ## LDAP Authentication
 
 FAB supports authenticating user credentials against an LDAP server.

Reply via email to