diff --git a/mcpgateway/config.py b/mcpgateway/config.py index 271789a313..1ff07c91f6 100644 --- a/mcpgateway/config.py +++ b/mcpgateway/config.py @@ -385,6 +385,7 @@ class Settings(BaseSettings): sso_entra_graph_api_enabled: bool = Field(default=True, description="Enable Microsoft Graph fallback for EntraID groups overage claims") sso_entra_graph_api_timeout: int = Field(default=10, ge=1, le=120, description="Timeout in seconds for Microsoft Graph group fallback requests") sso_entra_graph_api_max_groups: int = Field(default=0, ge=0, description="Maximum groups to keep from Graph fallback (0 = no limit)") + sso_entra_team_mapping: Dict[str, Any] = Field(default_factory=dict, description="Map EntraID groups to ContextForge teams (JSON: {group_id: {team_id: ..., role: member|owner}})") sso_adfs_enabled: bool = Field(default=False, description="Enable ADFS OIDC authentication") sso_adfs_client_id: Optional[str] = Field(default=None, description="ADFS OAuth client ID") diff --git a/mcpgateway/utils/sso_bootstrap.py b/mcpgateway/utils/sso_bootstrap.py index a1683fde77..2059ae1dd9 100644 --- a/mcpgateway/utils/sso_bootstrap.py +++ b/mcpgateway/utils/sso_bootstrap.py @@ -225,7 +225,7 @@ def get_predefined_sso_providers() -> List[Dict]: "scope": "openid profile email User.Read", "trusted_domains": settings.sso_trusted_domains, "auto_create_users": settings.sso_auto_create_users, - "team_mapping": {}, + "team_mapping": settings.sso_entra_team_mapping, "provider_metadata": { "groups_claim": settings.sso_entra_groups_claim, "role_mappings": settings.sso_entra_role_mappings, @@ -414,9 +414,12 @@ async def bootstrap_sso_providers() -> None: if existing_provider.scope and existing_provider.scope != "openid profile email" and provider_config.get("scope") == "openid profile email": provider_config["scope"] = existing_provider.scope - # Preserve DB team_mapping if env provides empty mapping - if existing_provider.team_mapping and not provider_config.get("team_mapping"): - provider_config["team_mapping"] = existing_provider.team_mapping + # Smart merge for team_mapping: same strategy as provider_metadata. + # Env provides base mapping, DB values override (Admin API changes survive restarts). + if "team_mapping" in provider_config: + env_mapping = provider_config["team_mapping"] or {} + db_mapping = existing_provider.team_mapping or {} + provider_config["team_mapping"] = {**env_mapping, **db_mapping} updated = await sso_service.update_provider(existing_provider.id, provider_config) if updated: