You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@superset.apache.org by GitBox <gi...@apache.org> on 2022/03/31 12:29:46 UTC

[GitHub] [superset] nigzak opened a new issue #19461: Superset does not seem to support refresh token (OpenID Connect with authlib) and I get "hardly" kicked out after token expired

nigzak opened a new issue #19461:
URL: https://github.com/apache/superset/issues/19461


   I am using superset with custom OAUTH configuration which is using a login token which expires after 30m.
   Until this time is not expired all works
   If the time expires I get error messages, in the logfile in the server is standing 401
   If I open the main page again (and I am not in some chart) I get a "login" page again displayed
   
   ... this is in case I am modifying some charts very bad
   
   Superset 1.4.1 (Docker) with custom security
   
   #### How to reproduce the bug
   
   1. Login
   2. Open some charts
   3. wait until token from OIDC (OpenID Connect) expires
   4. execute some logic
   
   ### Expected results
   
   Refresh token is executed (no visible refreshment for user)
   
   
   ### Actual results
   
   User login gets invalid and he gets kicked out, all not saved work is lost
   
   
   
   ### Environment
   
   (please complete the following information):
   
   Chrome browser
   Superset 1.4.1 official docker image with authlib 0.15.5 (1.0.0 is buggy)
   
   Dockerfile
   `
   FROM apache/superset:1.4.1
   USER superset:superset
   COPY custom_sso_security_manager.py /app/pythonpath/custom_sso_security_manager.py
   COPY superset_config.py /app/pythonpath/superset_config.py
   COPY rootca.pem /app/pythonpath/rootca.pem  -- <== my database requires a certificate (postgreSQL)
   
   USER root:root
   
   RUN apt -y update
   RUN apt-get -y --only-upgrade install libsasl2-2  -- <== LIBSASL2 has a open VCE in current image, I update here to fix this
   
   RUN chown superset:superset /app/pythonpath/custom_sso_security_manager.py
   RUN chown superset:superset /app/pythonpath/superset_config.py
   RUN chown superset:superset /app/pythonpath/rootca.pem
   RUN chmod +x /app/pythonpath/custom_sso_security_manager.py
   RUN chmod +x /app/pythonpath/superset_config.py
   
   RUN pip install authlib==0.15.5  -- <== using V1.0.0 is not working, if you don't type the version V1.0.0 is installed
   
   
   USER superset:superset
   `
   
   
   ### Checklist
   
   I googled and tried many things but I did not find a working solution
   
   ### Additional context
   
   HINT: removed the URL and replaced with "xx"
   
   superset_config.py
   `
   from flask_appbuilder.security.manager import AUTH_OID,AUTH_REMOTE_USER,AUTH_DB, AUTH_LDAP, AUTH_OAUTH
   import os
   
   from custom_sso_security_manager import CustomSsoSecurityManager
   CUSTOM_SECURITY_MANAGER = CustomSsoSecurityManager
   
   
   basedir = os.path.abspath(os.path.dirname(__file__))
   SUPERSET_WORKERS = 4
   
   # CRYPTION STUFF -----------------------------------------------------------------------------------
   SECRET_KEY = os.getenv('SUPERSET_SECRET_KEY')
   
   # DATABASE STUFF -----------------------------------------------------------------------------------
   PSQLHOST=os.getenv('PSQL_HOST')
   PSQLPORT=os.getenv('PSQL_PORT')
   PSQLUSER=os.getenv('PSQL_USER')
   PSQLPASS=os.getenv('PSQL_PASS')
   PSQLDB=os.getenv('PSQL_DB')
   
   PSQLSSLMODE = os.getenv('PSQL_SSL_MODE')
   PSQLSSLROOTCA = os.getenv('PSQL_SSL_ROOTCA')
   
   print (' USING DB FOR SQLALCHEMY ')
   print ('HOST: ' + str(PSQLHOST))
   print ('PORT: ' + str(PSQLPORT))
   print ('SSL_MODE: ' + PSQLSSLMODE)
   print ('SSL_CA: ' + PSQLSSLROOTCA)
   
   
   if PSQLSSLMODE != None and PSQLSSLMODE != "" and PSQLSSLROOTCA != None and PSQLSSLROOTCA != "":
   	print('PSQL: SSL MODE USED MODE=' + PSQLSSLMODE + ' CA=' + PSQLSSLROOTCA)
   	SQLALCHEMY_DATABASE_URI = 'postgresql+psycopg2://' + PSQLUSER + ':' + PSQLPASS + '@' + PSQLHOST + ':' + str(PSQLPORT) + '/' + PSQLDB + '?sslmode=' + PSQLSSLMODE + '&sslrootcert=' + PSQLSSLROOTCA  # PSQL must be parsed to STR, otherwise concatenation fails (INT vs STR)
   else:
   	print('PSQL: NO SSL MODE USED')
   	SQLALCHEMY_DATABASE_URI = 'postgresql+psycopg2://' + PSQLUSER + ':' + PSQLPASS + '@' + PSQLHOST + ':' + str(PSQLPORT) + '/' + PSQLDB 
   
   
   # AUTHENTIFICATION STUFF ---------------------------------------------------------------------------
   OIDCCID=os.getenv('OIDC_CLIENT_ID')
   OIDCCS=os.getenv('OIDC_CLIENT_SECRET')
   CSRF_ENABLED = True
   AUTH_TYPE = AUTH_OAUTH
   AUTH_USER_REGISTRATION = False
   
   
   AUTH_ROLES_MAPPING = {
       "X.Y": ["test"],
       "x.z": ["Admin"]
   }
   AUTH_ROLES_SYNC_AT_LOGIN = True
   PERMANENT_SESSION_LIFETIME = 600
   OAUTH_PROVIDERS = [
       {a
           'name': 'XX',
           'icon': 'XX',
           'token_key': 'access_token',
           'remote_app': {
               'client_id': OIDCCID,
               'client_secret': OIDCCS,
               'api_base_url': 'https://sso.xx.com/as/',
               'client_kwargs':{
                 'scope': 'openid email profile authorization_group entitlement_group scoped_entitlement offline_access'
               },
               'request_token_url': None,
               'access_token_url': 'https://sso.xx.com/as/token.oauth2',
   			'refresh_token_url' : 'https://sso.xx.com/as/token.oauth2',
               'authorize_url': 'https://sso.xx.com/as/authorization.oauth2',
   			'code_challenge_method':'S256',
           }
       }
   ]
   
   ENABLE_PROXY_FIX = True
   PREFERRED_URL_SCHEME = 'https'
   `
   
   custom_sso_security_manager.py
   `
   from superset.security import SupersetSecurityManager
   import logging
   
   
   class CustomSsoSecurityManager(SupersetSecurityManager):
   	def oauth_user_info(self, provider, response=None):
   		access_token = response["access_token"]
   		headers = {'Authorization': 'Bearer %s' % (access_token)}
   		me = self.appbuilder.sm.oauth_remotes[provider].get("https://sso.xx.com/idp/userinfo.openid", headers=headers)
   		data = me.json()
   		logging.debug("User info from xx: %s", data)      
   		logging.debug("Entitlements: %s", data.get("entitlement_group", []))
   		return {
               "username": data.get("sub", ""),
               "first_name": data.get("given_name", ""),
               "last_name": data.get("family_name", ""),
               "email": data.get("email", ""),
               "role_keys": data.get("entitlement_group", []),
   		}
           
   
   `
   
   
   ### HINT
   
   it could be that I have some configuration missunderstandings ... if this is the case please let me know how to fix this ...


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org