Docker部署的Apache Superset集成AWS Cognito时登录失败,提示'Invalid login. Please try again'
我之前帮不少人排查过Superset和Cognito OAuth集成的问题,从你描述的流程和日志来看,核心问题肯定出在Superset获取Cognito返回的用户信息这一步——日志里的Error returning OAuth user info已经把指向性拉满了,至于那个Werkzeug的警告,暂时可以先放一放,不是当前登录失败的直接原因。
先理清楚你的问题链路:Cognito那边已经验证通过了,但跳回Superset后,Superset没法正确解析Cognito返回的用户数据,所以判定登录无效,把你打回登录页。
你当前配置里的坑
看你的superset_config.py,你自己写了exchange_oauth_code_for_token和oauth_authorized_callback两个自定义函数,但其实Superset基于的Flask-AppBuilder(FAB)已经内置了一套完整的OAuth处理逻辑,自定义回调很容易和FAB的会话管理、用户创建流程冲突——你写的回调可能没有返回FAB需要的用户信息结构,也没有触发FAB的登录会话创建,自然就会提示“无效登录”。
具体的修复步骤
我建议你简化配置,去掉自定义的回调逻辑,改用FAB的原生OAuth流程,再配合一个自定义的用户信息解析函数,就能解决问题:
1. 替换你的superset_config.py配置
把原来的配置改成下面这样,我已经帮你调整了核心部分:
# Superset Configuration RATELIMIT_STORAGE_URI = 'redis://redis:9999/0' ENABLE_PROXY_FIX = True SESSION_COOKIE_SECURE = True SESSION_COOKIE_SAMESITE = "Lax" SUPERSET_WEBSERVER_PROTO = 'https' # Import necessary modules import os import logging from flask_appbuilder.security.manager import AUTH_OAUTH from jose import jwt # Enable OAuth authentication AUTH_TYPE = AUTH_OAUTH AUTH_USER_REGISTRATION = True AUTH_USER_REGISTRATION_ROLE = "Admin" # Cognito基础配置(根据你的实际信息调整) COGNITO_REGION = 'eu-central-1' COGNITO_USER_POOL_ID = 'eu-central-1_123456' COGNITO_CLIENT_ID = '111' COGNITO_CLIENT_SECRET = 'xxx' COGNITO_DOMAIN = 'momo1.auth.eu-central-1.amazoncognito.com' # 配置OAuth提供商 OAUTH_PROVIDERS = [ { 'name': 'cognito', 'token_key': 'access_token', 'icon': 'fa-cogs', 'remote_app': { 'client_id': COGNITO_CLIENT_ID, 'client_secret': COGNITO_CLIENT_SECRET, 'client_kwargs': { 'scope': 'openid email profile', # 必须包含这些scope才能获取用户信息 'redirect_uri': 'https://momo.com/oauth-authorized/cognito' }, 'access_token_url': f'https://{COGNITO_DOMAIN}/oauth2/token', 'authorize_url': f'https://{COGNITO_DOMAIN}/oauth2/authorize', 'api_base_url': f'https://{COGNITO_DOMAIN}/', } } ] # 自定义用户信息解析函数:把Cognito返回的格式转成Superset能识别的结构 def get_cognito_user_info(remote_app, token, **kwargs): logger = logging.getLogger(__name__) try: # 方式一:调用Cognito的UserInfo接口获取用户数据 resp = remote_app.get('oauth2/userInfo', token=token) resp.raise_for_status() user_info = resp.json() logger.info(f"从Cognito获取到的用户信息:{user_info}") # 加日志方便调试 # 方式二:解码ID Token获取用户数据(如果方式一有问题可以试试这个) # id_token = token.get('id_token') # user_info = jwt.decode( # id_token, # options={"verify_signature": False}, # 生产环境建议用Cognito的公钥验证签名 # audience=COGNITO_CLIENT_ID # ) # 转成Superset需要的格式 return { 'username': user_info.get('email'), 'first_name': user_info.get('given_name') or user_info.get('name', ''), 'last_name': user_info.get('family_name') or '', 'email': user_info.get('email') } except Exception as e: logger.error(f"解析Cognito用户信息失败:{str(e)}") raise # 抛出错误让FAB捕获,方便排查 # 告诉Superset用我们自定义的函数解析用户信息 OAUTH_USER_INFO_FUNCTION = get_cognito_user_info
2. 关键修复点说明
- 删掉了你自定义的回调函数:FAB自带的OAuth流程已经能处理授权码换token、会话创建这些操作,自定义反而容易踩坑;
- 新增了
OAUTH_USER_INFO_FUNCTION:这是核心!Cognito返回的用户信息格式和Superset默认预期的格式不匹配,必须转成Superset能识别的username/first_name/last_name/email结构; - 加了调试日志:方便你看Cognito到底返回了什么数据,要是有缺失的字段,你可以在Cognito用户池的属性设置里检查是否开启了对应属性的返回。
3. 额外的排查确认点
虽然你说Cognito配置没问题,但还是再核对一遍:
- 确认Cognito App Client的回调URL和你配置里的
redirect_uri完全一致(大小写、路径都不能错); - 确认App Client启用了授权码流程,并且scopes包含
openid、email、profile; - 确认Cognito用户池里的目标用户,
email属性是已验证状态(Superset默认用邮箱作为用户唯一标识); - 用Superset官方推荐的Werkzeug版本:比如Superset 3.x对应Werkzeug 2.3.x左右,不要随便降级到太老的版本。
4. 调试技巧
如果还是有问题,你可以在Superset容器里查看更详细的日志,比如把日志级别调到DEBUG:
# 在superset_config.py里加一行 logging.basicConfig(level=logging.DEBUG)
这样能看到更多OAuth流程的细节,比如Cognito返回的token内容、用户信息接口的响应等。
最后总结
你之前的问题本质是“自定义逻辑和Superset内置框架流程冲突”,导致用户信息无法被正确解析,进而触发登录失败提示。改用FAB原生流程+自定义用户信息解析函数,应该就能解决这个问题了。
备注:内容来源于stack exchange,提问作者nunsy grey

