Apache Superset集成Azure Entra ID登出重登遇502错误排查
问题描述
我已成功为Apache Superset配置Azure Entra ID双因素认证,但登出后再次登录时出现502 Bad Gateway错误,浏览器地址栏显示:https://my-app.com/login/azure?next=,且Superset似乎未在登出时清除缓存,只有手动清除浏览器历史记录后才能正常登录。
Nginx配置
server { server_name my-app.rw; location / { proxy_pass http://127.0.0.1:8088; # Changed to localhost proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_redirect http:// $scheme://; } location = /logout { proxy_pass http://127.0.0.1:8088/logout; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_redirect http:// $scheme://; proxy_redirect off; # Critical for Azure AD } listen 443 ssl; ssl_certificate /etc/letsencrypt/live/my-app.rw/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/my-app.rw/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; }
superset_config.py配置
class CustomSecurityManager(SupersetSecurityManager): def oauth_user_info(self, provider, response=None): if provider != 'azure': # Handle other providers or return empty return {} try: # Log the response for debugging logger.debug(f"OAuth response for {provider}: {response}") remote = self.appbuilder.sm.oauth_remotes[provider] # Log the authorize URL (initial redirect to Azure AD) logger.debug(f"Authorize URL: {remote.authorize_url}") # Should match Azure AD # Log the token exchange URL logger.debug(f"Token URL: {remote.access_token_url}") # Should be Azure AD's /token endpoint # More robust token handling headers = {} if response.get('access_token'): headers['Authorization'] = f"Bearer {response.get('access_token')}" # Make the API request me = remote.get('https://graph.microsoft.com/v1.0/me', token=response, headers=headers) # Check for success if me.status_code != 200: logger.error(f"Microsoft Graph API error: {me.status_code} - {me.text}") return {} # Parse the response user_data = me.json() logger.debug(f"User data from Microsoft Graph: {user_data}") # Extract user information email = user_data.get('mail') if not email: upn = user_data.get('userPrincipalName') if upn: email = upn.split('#EXT#')[0].replace('_', '@') existing_user = self.appbuilder.get_session.query(User).filter_by(email=email).first() username = existing_user.username if existing_user else email return { 'email': email, 'username': username, 'first_name': user_data.get('givenName', ''), 'last_name': user_data.get('surname', ''), } except Exception as e: # Log the full error with traceback logger.exception(f"OAuth error for {provider}: {str(e)}") # Return empty dict instead of raising to prevent authentication failures return {} class CustomAuthDBView(AuthDBView): @expose('/logout') def logout(self): # Clear local session self.appbuilder.sm.logout_user() # Redirect to Azure AD logout return redirect( "https://login.microsoftonline.com/974x/oauth2/v2.0/logout" "?post_logout_redirect_uri=https://my-app.rw/login" ) CUSTOM_SECURITY_MANAGER = CustomSecurityManager # Register the view APP_BUILDER_VIEWS = [CustomAuthDBView] ENABLE_PROXY_FIX = True AUTH_TYPE = AUTH_OAUTH OAUTH_PROVIDERS = [ { "name": "azure", "icon": "fa-windows", "token_key": "access_token", "remote_app": { "client_id": "0722xxx", "client_secret": "ky8xxx", "api_base_url": "https://graph.microsoft.com/v1.0/", "server_metadata_url": "https://login.microsoftonline.com/974xx/v2.0/.well-known/openid-configuration", "redirect_uri": "https://my-app.rw/oauth-authorized/azure", "logout_url": ( "https://login.microsoftonline.com/9xxx/oauth2/v2.0/logout" "?post_logout_redirect_uri=https://my-app.rw/logout" ), "client_kwargs": { "scope": "openid profile email User.Read", }, "request_token_url": None, "access_token_url": "https://login.microsoftonline.com/974x/oauth2/v2.0/token", "authorize_url": "https://login.microsoftonline.com/974x/oauth2/v2.0/authorize", }, } ]
解决方案
1. 修复登出流程的重定向冲突
当前自定义登出逻辑与OAUTH_PROVIDERS中的logout_url配置存在循环重定向问题,导致Nginx返回502错误:
- 移除
OAUTH_PROVIDERS中的logout_url配置,让自定义登出逻辑完全接管流程 - 确保Azure AD的
post_logout_redirect_uri指向登录页而非/logout
修改后的OAUTH_PROVIDERS片段:
OAUTH_PROVIDERS = [ { "name": "azure", "icon": "fa-windows", "token_key": "access_token", "remote_app": { "client_id": "0722xxx", "client_secret": "ky8xxx", "api_base_url": "https://graph.microsoft.com/v1.0/", "server_metadata_url": "https://login.microsoftonline.com/974xx/v2.0/.well-known/openid-configuration", "redirect_uri": "https://my-app.rw/oauth-authorized/azure", # 移除logout_url配置项 "client_kwargs": { "scope": "openid profile email User.Read", }, "request_token_url": None, "access_token_url": "https://login.microsoftonline.com/974x/oauth2/v2.0/token", "authorize_url": "https://login.microsoftonline.com/974x/oauth2/v2.0/authorize", }, } ]
2. 强化会话清除逻辑
在自定义登出方法中,除了调用logout_user(),手动清除Superset相关Cookie,避免缓存残留:
修改CustomAuthDBView的logout方法:
class CustomAuthDBView(AuthDBView): @expose('/logout') def logout(self): # 清除本地会话 self.appbuilder.sm.logout_user() # 重定向到Azure AD登出页 response = redirect( "https://login.microsoftonline.com/974x/oauth2/v2.0/logout" "?post_logout_redirect_uri=https://my-app.rw/login" ) # 清除Superset会话Cookie response.delete_cookie('session') response.delete_cookie('superset_session') return response
3. 调整Nginx缓存规则
确保Nginx不对登录、登出及OAuth授权路径进行缓存:
修改Nginx的location /块:
location / { proxy_pass http://127.0.0.1:8088; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_redirect http:// $scheme://; # 排除关键路径的缓存 proxy_no_cache $request_uri ~* (/login|/logout|/oauth-authorized); proxy_cache_bypass $request_uri ~* (/login|/logout|/oauth-authorized); }
简化location = /logout块配置:
location = /logout { proxy_pass http://127.0.0.1:8088/logout; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_redirect off; }
4. 验证Azure AD应用配置
- 确认Azure AD应用的
重定向URI包含https://my-app.rw/oauth-authorized/azure - 将
https://my-app.rw/login添加到Azure AD应用的已注销重定向URI列表中
5. 重启服务验证
- 重启Nginx:
sudo systemctl restart nginx - 重启Superset:
superset restart - 测试登出后重新登录,确认502错误消失,无需手动清除缓存即可正常登录
内容的提问来源于stack exchange,提问作者Mo1
相关产品推荐
相关产品推荐

