Apache Superset 和 Auth0 返回“意外的关键字参数‘范围’”

Posted

技术标签:

【中文标题】Apache Superset 和 Auth0 返回“意外的关键字参数‘范围’”【英文标题】:Apache Superset and Auth0 returns "unexpected keyword argument 'scope'" 【发布时间】:2021-12-07 05:32:53 【问题描述】:

前段时间,我使用 AWS Cognito 成功地将 Superset 身份验证与 Oauth 集成。

现在我正在尝试对 Auth0 做同样的事情,重用以前的配置并根据 Auth0 文档更改端点。

很遗憾,登录失败,Superset 的日志返回如下信息:

2021-10-20 10:30:48,886:ERROR:flask_appbuilder.security.views:Error on OAuth authorize: request() got an unexpected keyword argument 'scope'

这是superset_config.py中的Oauth配置:

from superset.security import SupersetSecurityManager

import json
import logging

logger = logging.getLogger(__name__)

class CustomSsoSecurityManager(SupersetSecurityManager):
    def oauth_user_info(self, provider, response=None):
        if provider == 'auth0':
            res = self.appbuilder.sm.oauth_remotes[provider].get('userinfo')
            if res.raw.status != 200:
                logger.error('Failed to obtain user info: %s', res.data)
                return
            me = json.loads(res._content)
            logger.warning(" user_data: %s", me)
            prefix = 'Superset'
            logging.warning("user_data: 0".format(me))
            return 
                'username' : me['email'],
                'name' : me['name'],
                'email' : me['email'],
                'first_name': me['given_name'],
                'last_name': me['family_name'],
            

AUTH_TYPE = AUTH_OAUTH
AUTH_USER_REGISTRATION = True
AUTH_USER_REGISTRATION_ROLE = "Public"

AUTH0_URL = os.getenv('AUTH0_URL')
AUTH0_CLIENT_KEY = os.getenv('AUTH0_CLIENT_KEY')
AUTH0_CLIENT_SECRET = os.getenv('AUTH0_CLIENT_SECRET')

OAUTH_PROVIDERS = [
    'name':'auth0',
    'token_key': 'access_token',
    'icon':'fa-at',
    'url': AUTH0_URL,
    'remote_app': 
        'client_id': AUTH0_CLIENT_KEY,
        'client_secret': AUTH0_CLIENT_SECRET,
        'request_token_params': 
            'scope': 'email openid profile'
        ,
        'response_type': 'token_id',
        'base_url': AUTH0_URL,
        'access_token_url': os.path.join(AUTH0_URL, 'oauth/token'),
        'authorize_url': os.path.join(AUTH0_URL, 'authorize'),
        'access_token_method':'POST',
        'request_token_url': os.path.join(AUTH0_URL, 'oauth/token'),
        'api_base_url': AUTH0_URL,
        
    
]

CUSTOM_SECURITY_MANAGER = CustomSsoSecurityManager

我已经为response_type(代码、令牌、令牌_id)尝试了不同的值。

还尝试将 request_token_url 留空,在这种情况下,错误会发生变化,因为用户数据似乎是一个空字典:

2021-10-13 15:52:10,358:WARNING:superset_config: user_data: 
2021-10-13 15:52:10,358:WARNING:root:user_data: 
2021-10-13 15:52:10,358:ERROR:flask_appbuilder.security.views:Error returning OAuth user info: 'email'

所以我假设令牌实际上是返回的,我不明白为什么 Flask 抱怨属性“范围”。

也试过this,因为它看起来与我的问题非常相似,但这些配置都不适合我。

【问题讨论】:

【参考方案1】:

根据 Flask Documentation, 尝试使用client_kwargs 而不是request_token_params 键。

示例:


    'name':'google',
    'icon':'fa-google',
    'token_key':'access_token',
    'remote_app': 
            'client_id':'GOOGLE_KEY',
            'client_secret':'GOOGLE_SECRET',
            'api_base_url':'https://www.googleapis.com/oauth2/v2/',
            'client_kwargs':
              'scope': 'email profile'
            ,
            'request_token_url':None,
            'access_token_url':'https://accounts.google.com/o/oauth2/token',
            'authorize_url':'https://accounts.google.com/o/oauth2/auth'
    
,

【讨论】:

天哪,成功了!非常感谢卡马尔!将使用完整的工作配置更新我的问题以供将来参考。只是无法理解为什么有大量的 Flask/Superset 指南使用 request_token_params 来设置范围...... 我的猜测是那些指南很旧,flask 可能已经更新了键名。所以最好在官方网站上确认。【参考方案2】:

希望你有两个文件,分别是 custom_sso_security_manager.py 和 superset_config.py

你能从 return 和 try(custom_sso_security_manager.py) 中删除以下两行吗?

'first_name': me['given_name'],
'last_name': me['family_name'],

【讨论】:

嗨 Satish,所有代码都在同一个文件 superset_config.py 中,正如我所说,相同的配置目前正在另一个针对 AWS Cognito 进行身份验证的 Superset 部署中工作。我试图从用户数据字典中删除这两项,但它引发了相同的错误:“得到了一个意外的关键字参数'范围'”,这发生在代码的不同部分。【参考方案3】:

这是供将来参考,虽然我接受了Kamal 的回答。

原来设置请求令牌范围的正确参数是client_kwargs,而不是request_token_params

这是针对 Auth0 验证 Superset 的有效配置:

## Enable OAuth authentication
from flask_appbuilder.security.manager import (
    AUTH_OAUTH,
)

from superset.security import SupersetSecurityManager

import json
import logging
import string
import random

nonce = ''.join(random.choices(string.ascii_uppercase + string.digits + string.ascii_lowercase, k = 30))

logger = logging.getLogger(__name__)

class CustomSsoSecurityManager(SupersetSecurityManager):
    def oauth_user_info(self, provider, response=None):
        if provider == 'auth0':
            res = self.appbuilder.sm.oauth_remotes[provider].get('userinfo')
            if res.raw.status != 200:
                logger.error('Failed to obtain user info: %s', res.json())
                return
            me = res.json()
            return 
                'username' : me['email'],
                'name' : me['name'],
                'email' : me['email'],
            

AUTH_TYPE = AUTH_OAUTH
AUTH_USER_REGISTRATION = True
AUTH_USER_REGISTRATION_ROLE = "Public"

AUTH0_URL = os.getenv('AUTH0_URL')
AUTH0_CLIENT_KEY = os.getenv('AUTH0_CLIENT_KEY')
AUTH0_CLIENT_SECRET = os.getenv('AUTH0_CLIENT_SECRET')

OAUTH_PROVIDERS = [
     'name':'auth0',
      'token_key':'access_token',
      'icon':'fa-at',
      'remote_app': 
          'api_base_url': AUTH0_URL,
          'client_id': AUTH0_CLIENT_KEY,  
          'client_secret': AUTH0_CLIENT_SECRET, 
          'server_metadata_url': os.path.join(AUTH0_URL, '.well-known/openid-configuration'),
          'client_kwargs': 
              'scope': 'openid profile email'
          ,
         'response_type': 'code token',
         'nonce': nonce,
      
  
]

CUSTOM_SECURITY_MANAGER = CustomSsoSecurityManager

【讨论】:

以上是关于Apache Superset 和 Auth0 返回“意外的关键字参数‘范围’”的主要内容,如果未能解决你的问题,请参考以下文章

Apache Superset从入门到放弃(基于python3.6.9)

有没有办法为Superset提供apache Solr后端?

Apache Superset从入门到放弃(基于python3.6.9)

Apache Superset从入门到放弃(基于python3.6.9)

安装Apache Superset--基于Docker的安装配置

Apache Superset二次开发环境配置