anuvdas commented on issue #44868:
URL: https://github.com/apache/superset/issues/44868#issuecomment-6075230813
@dosu
In the superset_config.py file below is the entry for CUSTOM_SECURITY_MANAGER
```
if os.getenv('ENABLE_W3ID_AUTH', 'False').lower() == 'true':
from w3id_oidc_security_manager import W3IDSecurityManager
CUSTOM_SECURITY_MANAGER = W3IDSecurityManager
```
And in the w3id_oidc_security_manager.py file below is the entry
```
from flask_appbuilder.baseviews import expose
from flask_appbuilder.security.views import AuthOAuthView
from flask_login import login_user, logout_user
from superset.security import SupersetSecurityManager
import os
import logging
logger = logging.getLogger(__name__)
class W3IDSecurityManager(SupersetSecurityManager):
'''
Custom security manager to support w3id OpenID Connect with auto-created
groups
'''
def auth_user_oauth(self, userinfo):
"""
Assign users to their w3id groups after OAuth login.
:param userinfo: dict with user information from oauth_user_info()
:return: User object with groups assigned
"""
# Call parent method to create/update the user
user = super().auth_user_oauth(userinfo)
if os.environ.get('AUTH_GROUPS_SYNC_AT_LOGIN', '').lower() != 'true':
return user
if user:
# Get the groups that should be assigned (from oauth_user_info
return)
group_names = userinfo.get('groups', [])
if group_names:
logger.info(f"Assigning user {user.username} to
{len(group_names)} groups: {group_names}")
# Get group prefix to identify w3id-managed groups
group_prefix = os.environ.get('SUPERSET_GROUP_PREFIX',
'superset-')
# Safety check: ensure user.groups exists and is not None
if user.groups is None:
logger.warning(f"User {user.username} has None groups,
initializing to empty list")
user.groups = []
# Remove user from old w3id-managed groups (those starting
with prefix)
# This ensures group membership stays in sync with w3id
for group in list(user.groups):
if group and group.name and
group.name.startswith(group_prefix):
user.groups.remove(group)
logger.debug(f"Removed user from old W3ID group:
{group.name}")
# Add user to new w3id groups
for group_name in group_names:
if not group_name:
logger.warning("Skipping empty group name")
continue
group = self.find_group(group_name)
if group:
if group not in user.groups:
user.groups.append(group)
logger.info(f"Added user to group: {group_name}")
else:
logger.warning(f"Group not found (should have been
created): {group_name}")
# Commit changes to database
self.appbuilder.session.commit()
logger.info(f"Successfully assigned user {user.username} to
groups")
return user
def oauth_user_info(self, provider, response=None):
if provider == 'w3id-oidc':
# As OpenID connect 1.0 provider, w3id provides id_token in
response
user_info =
self.appbuilder.sm.oauth_remotes[provider].parse_id_token(response, None)
# DEBUG: Print all claims to see what W3ID returns
logger.debug("W3ID Token Claims: %s", user_info)
if os.environ.get('AUTH_GROUPS_SYNC_AT_LOGIN', '').lower() !=
'true':
return {
# use email as username
'username': user_info['email'],
'email': user_info['email'],
}
# Extract blueGroups from W3ID token
# W3ID returns IBM groups in the 'blueGroups' claim
blue_groups = user_info.get('blueGroups', [])
logger.info(f"User {user_info.get('email')} has {len(blue_groups
or [])} total Blue Groups")
# Get group prefix from environment (default: 'superset-')
group_prefix = os.environ.get('SUPERSET_GROUP_PREFIX',
'superset-')
# Filter to only Superset-related groups (those with the prefix)
superset_groups = [g for g in blue_groups if g and
g.startswith(group_prefix)]
logger.info(f"Filtered to {len(superset_groups)} Superset
groups: {superset_groups}")
# Auto-create Superset groups if they don't exist
for group_name in superset_groups:
existing_group = self.appbuilder.sm.find_group(group_name)
if not existing_group:
logger.info(f"Auto-creating Superset group:
{group_name}")
self.appbuilder.sm.add_group(
name=group_name,
label=group_name,
description=f"Auto-created from Blue Group:
{group_name}"
)
else:
logger.debug(f"Group already exists: {group_name}")
return {
# use email as username
'username': user_info['email'],
'email': user_info['email'],
'first_name': user_info.get('firstName', ''),
'last_name': user_info.get('lastName', ''),
# Assign user to Superset groups (roles assigned to groups
in UI)
'groups': superset_groups
}
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]