使用 Apache Superset 实现 OpenID。 AttributeError:“bool”对象没有属性“is_active”

问题描述 投票:0回答:1

我正在尝试在 Apache Superset 中实现 OpenID。我使用 Broadcom CA-SSO 作为我的提供商。我在 Stack Overflow 中发现了类似的帖子,其中有人使用 Keycloak 实现(Using KeyCloak(OpenID Connect) with Apache SuperSet) 我发现这篇文章对我的实施很有帮助。我也遵循了类似的方法。

我已经能够使用 CA-SSO 验证我的用户身份。但是,当浏览器到达回调路由时,superset 会抛出以下错误:

Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 2464, 
in __call__
return self.wsgi_app(environ, start_response)
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 2450, 
in wsgi_app
response = self.handle_exception(e)
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1867, 
in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.7/site-packages/flask/_compat.py", line 
39, in reraise
raise value
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 2447, 
in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1952, 
in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1821, 
in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.7/site-packages/flask/_compat.py", line 
39, in reraise
raise value
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1950, 
in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python3.7/site-packages/flask/app.py", line 1936, 
in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/app/superset/custom_security.py", line 34, in login
return handle_login()
File "/usr/local/lib/python3.7/site-packages/flask_oidc/__init__.py", 
line 487, in decorated
return view_func(*args, **kwargs)
File "/app/superset/custom_security.py", line 31, in handle_login
login_user(user, remember=False)
File "/usr/local/lib/python3.7/site-packages/flask_login/utils.py", 
line 158, in login_user
if not force and not user.is_active:
AttributeError: 'bool' object has no attribute 'is_active'

这是我的实现:

client_secrets.json

{
    "web": {
        "issuer": "https://<SSO DOMAIN>",
        "auth_uri": "https://<SSO DOMAIN>/authorize",
        "client_id": "<CLIENT ID>",
        "client_secret": "<CLIENT SECRET>",
        "redirect_uris": [
            "https://<YOUR DOMAIN>/oidc_callback"
        ],
        "userinfo_uri": "https://<SSO DOMAIN>/userinfo",
        "token_uri": "https://<SSO DOMAIN>/token",
        "token_introspection_uri": "https://<SSO DOMAIN>/introspect"
    }
}

安全.py

from flask import redirect, request
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
import logging

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

class OIDCSecurityManager(SupersetSecurityManager):
    authoidview = AuthOIDCView
    def __init__(self,appbuilder):
        super(OIDCSecurityManager, self).__init__(appbuilder)
        if self.auth_type == AUTH_OID:
            self.oid = OpenIDConnect(self.appbuilder.get_app)

在 superset/config.py 中

from security import OIDCSecurityManager
AUTH_TYPE = AUTH_OID
OIDC_CLIENT_SECRETS = <path_to_configuration_file>
OIDC_ID_TOKEN_COOKIE_SECURE = False
OIDC_REQUIRE_VERIFIED_EMAIL = False
AUTH_USER_REGISTRATION = True
AUTH_USER_REGISTRATION_ROLE = 'Gamma'
CUSTOM_SECURITY_MANAGER = OIDCSecurityManager
OVERWRITE_REDIRECT_URI = 'https://<YOUR DOMAIN>/oidc_callback'

我正在使用

flask-oidc
。我正在使用默认回调
/oidc_callback
。当超集重定向到
/authorize
端点时,redirect_uri 未被正确拾取。它选择的是本地主机而不是域名,因此我必须使用
OVERWRITE_REDIRECT_URI
标志。看来已经解决了这个问题。

另外,我正在使用 Nginx 反向代理

我还注意到一件奇怪的事情。我从

state
Url 解码了
/authorize
查询参数。它是一个带有键
csrf_token
destination
的对象。然后我解码了
destination
。它包含算法值和我的登录路线。但是,登录 URL 包含 localhost (
http://127.0.0.1:8088/login/
),而不是
https://<YOUR DOMAIN>/login
。这是正确的吗?

我正在使用 superset docker 来运行该应用程序。我是 python-flask 的新手。

python flask flask-login apache-superset
1个回答
0
投票

当我遇到这种情况时,我在堆栈跟踪之前看到了以下附加日志:

ERROR:flask_appbuilder.security.sqla.manager:Error adding new user to database. (sqlite3.IntegrityError) NOT NULL constraint failed: ab_user.first_name

因此,我更新了

add_user()
调用以设置空(即非空)名字和姓氏,此后它就起作用了。

user = sm.add_user(
                    username=info.get("sub"),
                    first_name=info.get("first") if info.get("first") is not None else "",
                    last_name=info.get("last") if info.get("last") is not None else "",
                    email=info.get("email") if info.get("last") is not None else "",
                    role=[security_manager.find_role(role) for role in roles],
                )
© www.soinside.com 2019 - 2024. All rights reserved.