Superset集成Keycloak OAuth后API调用JWT令牌报错求助
Superset API调用OAuth令牌报错:UUID无法转换为整数
问题背景
已完成Superset与Keycloak的SSO OAuth集成,Web端通过Cookie可正常访问,但调用Superset API时使用令牌出现错误,报错显示无法将UUID格式的身份标识转换为整数,需排查问题根源。
已配置信息
Superset JWT参数
JWT_ALGORITHM = 'RS256' JWT_PUBLIC_KEY = """ -----BEGIN PUBLIC KEY----- public_key_was_here -----END PUBLIC KEY----- """
获取Keycloak令牌命令
export TOKEN=`curl --request POST "$SSO_URL/auth/realms/$SSO_REALM/protocol/openid-connect/token?redirect_uri=$SUPERSET_URL/oauth-authorized/ozon_sso" \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode "username=$USERNAME" \ --data-urlencode "password=$PASSWORD" \ --data-urlencode 'scope=email profile roles' \ --data-urlencode 'grant_type=client_credentials' \ --data-urlencode 'client_id=k8s.superset' \ --data-urlencode "client_secret=$SSO_CLIENT_SECRET" | jq -r .access_token`
Superset API调用命令
curl -L --request GET $SUPERSET_URL/api/v1/dashboard/ --header "Authorization: Bearer $TOKEN" > ./dashboard_list.txt
报错日志详情
2022-12-15 07:24:00,487:ERROR:superset.views.base:invalid literal for int() with base 10: '674792eb-e01e-45b6-ad2e-75979db3d601' Traceback (most recent call last): File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1516, in full_dispatch_request rv = self.dispatch_request() File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1502, in dispatch_request return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args) File "/usr/local/lib/python3.8/site-packages/flask_appbuilder/security/decorators.py", line 94, in wraps verify_jwt_in_request() File "/usr/local/lib/python3.8/site-packages/flask_jwt_extended/view_decorators.py", line 83, in verify_jwt_in_request _request_ctx_stack.top.jwt_user = _load_user(jwt_header, jwt_data) File "/usr/local/lib/python3.8/site-packages/flask_jwt_extended/view_decorators.py", line 141, in _load_user user = user_lookup(jwt_header, jwt_data) File "/usr/local/lib/python3.8/site-packages/flask_jwt_extended/internal_utils.py", line 25, in user_lookup return jwt_manager._user_lookup_callback(*args, **kwargs) File "/usr/local/lib/python3.8/site-packages/flask_appbuilder/security/manager.py", line 2042, in load_user_jwt user = self.load_user(identity) File "/usr/local/lib/python3.8/site-packages/flask_appbuilder/security/manager.py", line 2038, in load_user return self.get_user_by_id(int(pk)) ValueError: invalid literal for int() with base 10: '674792eb-e01e-45b6-ad2e-75979db3d601' 10.220.74.237 - - [15/Dec/2022:07:24:00 +0000] "GET /api/v1/dashboard/ HTTP/1.1" 500 2337 "-" "curl/7.29.0"
错误原因与解决步骤
原因分析
报错栈显示,Flask-AppBuilder的load_user方法尝试将JWT令牌中的身份标识(UUID格式)转换为整数,但Superset默认用户ID为整数类型,核心矛盾是Keycloak返回的JWT中sub字段(用户身份)是UUID,而Superset期望用整数用户ID查找用户。
排查与解决
解析JWT确认
sub字段
本地使用JWT解析工具(如jwt命令行工具)解码获取的$TOKEN,查看sub字段是否为UUID格式。Keycloak端配置用户ID映射
在Keycloak客户端(k8s.superset)中添加用户属性映射:- 新建映射器,类型选择"User Attribute"
- 源属性设置为Superset用户的整数ID(对应
ab_user表的id字段) - 目标字段设为
sub,覆盖原UUID值
自定义Superset用户加载逻辑
若无法修改Keycloak配置,可自定义安全管理器重写用户加载逻辑:from flask_appbuilder.security.manager import SecurityManager from superset.security import SupersetSecurityManager class CustomSecurityManager(SupersetSecurityManager): def load_user_jwt(self, jwt_header, jwt_data): # 优先从JWT的邮箱或用户名字段查找用户 email = jwt_data.get('email') if email: return self.get_user_by_email(email) username = jwt_data.get('preferred_username') if username: return self.get_user_by_username(username) return super().load_user_jwt(jwt_header, jwt_data) CUSTOM_SECURITY_MANAGER = CustomSecurityManager将上述代码添加到Superset配置文件中,替换默认安全管理器。
调整Superset JWT配置
确保Superset指定正确的身份字段:# 若使用自定义的用户ID字段,替换为对应的字段名 JWT_IDENTITY_CLAIM = 'sub'
内容的提问来源于stack exchange,提问作者Andrey Larin
相关产品推荐
相关产品推荐

