SamWheating commented on issue #12782:
URL: https://github.com/apache/airflow/issues/12782#issuecomment-738232372


   As a workaround, its possible to write your own securityManager class, bring 
in the changes required and then use this class as your 
`SECURITY_MANAGER_CLASS` in webserver_config.py
   
   So then your webserver_cofig.py would look something like:
   
   ```python
   # Custom config for the FAB-based Airflow UI, bringing in changes from 
https://github.com/dpgaspar/Flask-AppBuilder/pull/1020
   
   import os
   
   from logging import getLogger
   
   from flask_appbuilder.security.manager import AUTH_OAUTH
   
   from airflow.configuration import conf
   from airflow.www_rbac.security import AirflowSecurityManager
   
   # Required settings in webserver_config.py
   basedir = os.path.abspath(os.path.dirname(__file__))
   AUTH_TYPE = AUTH_OAUTH
   SQLALCHEMY_DATABASE_URI = conf.get('core', 'SQL_ALCHEMY_CONN')
   WTF_CSRF_ENABLED = True
   
   log = getLogger(__name__)
   
   OAUTH_PROVIDERS = [{
     'name':'github',
       'token_key':'access_token',
       'icon':'fa-github',
           'remote_app': {
               'base_url':'https://www.googleapis.com/oauth2/v2/',
               'request_token_params':{
                   'scope': 'email profile'
               },
               'access_token_url':'https://accounts.google.com/o/oauth2/token',
               'authorize_url':'https://accounts.google.com/o/oauth2/auth',
               'request_token_url': None,
               'consumer_key': CONSUMER_KEY,
               'consumer_secret': SECRET_KEY,
           }
   }]
   
   class CustomSecurityManager(AirflowSecurityManager):
   
   
       def get_oauth_user_info(self, provider, resp):
           """
               Since there are different OAuth API's with different ways to
               retrieve user info
           """
           # for GITHUB
           if provider == "github" or provider == "githublocal":
               me = self.appbuilder.sm.oauth_remotes[provider].get("user")
               log.debug("User info from Github: {0}".format(me.data))
               email = me.data.get("email")
   
               if not email:
                   emails = 
self.appbuilder.sm.oauth_remotes[provider].get("user/emails")
                   email = emails.data[0].get("email")
   
               name = me.data.get("name:", "no-name given")
               name_parts = name.split(" ")
   
               if name_parts > 1:
                   first_name = name_parts[0]
                   last_name = name_parts[-1]
               else:
                   first_name = name
                   last_name = ""
   
               return {
                   "username": "github_" + me.data.get("login"),
                   "email": email,
                   "first_name": first_name,
                   "last_name": last_name
               }
           # for twitter
           if provider == "twitter":
               me = 
self.appbuilder.sm.oauth_remotes[provider].get("account/settings.json")
               log.debug("User info from Twitter: {0}".format(me.data))
               return {"username": "twitter_" + me.data.get("screen_name", "")}
           # for linkedin
           if provider == "linkedin":
               me = self.appbuilder.sm.oauth_remotes[provider].get(
                   
"people/~:(id,email-address,first-name,last-name)?format=json"
               )
               log.debug("User info from Linkedin: {0}".format(me.data))
               return {
                   "username": "linkedin_" + me.data.get("id", ""),
                   "email": me.data.get("email-address", ""),
                   "first_name": me.data.get("firstName", ""),
                   "last_name": me.data.get("lastName", ""),
               }
           # for Google
           if provider == "google":
               me = self.appbuilder.sm.oauth_remotes[provider].get("userinfo")
               log.debug("User info from Google: {0}".format(me.data))
               return {
                   "username": "google_" + me.data.get("id", ""),
                   "first_name": me.data.get("given_name", ""),
                   "last_name": me.data.get("family_name", ""),
                   "email": me.data.get("email", ""),
               }
           # for Azure AD Tenant. Azure OAuth response contains
           # JWT token which has user info.
           # JWT token needs to be base64 decoded.
           # https://docs.microsoft.com/en-us/azure/active-directory/develop/
           # active-directory-protocols-oauth-code
           if provider == "azure":
               log.debug("Azure response received : {0}".format(resp))
               id_token = resp["id_token"]
               log.debug(str(id_token))
               me = self._azure_jwt_token_parse(id_token)
               log.debug("Parse JWT token : {0}".format(me))
               return {
                   "name": me["name"],
                   "email": me["upn"],
                   "first_name": me["given_name"],
                   "last_name": me["family_name"],
                   "id": me["oid"],
                   "username": me["oid"],
               }
           else:
               return {}
   
   
   SECURITY_MANAGER_CLASS = CustomSecurityManager
   
   ```
   
   While this isn't great, the alternative is waiting for someone to update 
flask appbuilder and release a new version and then waiting for a new version 
of airflow to bring in the updated version of FAB. 


----------------------------------------------------------------
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.

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to