-
Notifications
You must be signed in to change notification settings - Fork 615
[FEATURE][AUTH]: Limitation for number of groups that can be fetched with EntraID #2201
Description
🧭 Type of Feature
- Enhancement to existing functionality
- New feature or capability
- New MCP-compliant server
- New component or integration
- Developer tooling or test improvement
- Packaging, automation and deployment (ex: pypi, docker, quay.io, kubernetes, terraform)
- Other (please describe below)
🧭 Epic
Title: Handle Azure AD/Entra ID Groups Overage Claims for Enterprise SSO Authentication
Goal: Enable admin group assignment and role mappings to work correctly for enterprise users with 100+ Azure AD group memberships by implementing Microsoft Graph API calls to retrieve groups when overage claims are detected.
Why now: Organizations with large Azure AD deployments cannot use admin groups or role mappings features because users with many group memberships (>200) trigger groups overage claims. This results in silent failures where users are created without proper permissions, requiring manual database updates as a workaround. This affects enterprise adoption and security posture.
🙋♂️ User Story 1: Admin Group Assignment with Groups Overage
As a: Platform Administrator configuring SSO authentication
I want: Users in designated Azure AD admin groups to automatically receive admin privileges upon SSO login
So that: I don't have to manually update the database to grant admin access to users who have 100+ total Azure AD group memberships
✅ Acceptance Criteria
Scenario: User with groups overage claim logs in for first time
Given a user "alice@enterprise.com" with 150 Azure AD group memberships
And the user is a member of admin group "89f32b79-914c-4322-aa3f-6c95765e2073"
And SSO_ENTRA_ADMIN_GROUPS is configured as ["89f32b79-914c-4322-aa3f-6c95765e2073"]
And the Azure AD token contains _claim_names and _claim_sources instead of direct groups
When the user completes SSO authentication
Then the application should detect the groups overage claim
And the application should call Microsoft Graph API to retrieve all user groups
And the user should be created with is_admin=true
And a log entry should indicate "Retrieved {count} groups from Graph API for alice@enterprise.com"
Scenario: User with groups overage claim logs in on subsequent visits
Given a user with groups overage claim already exists with is_admin=false
And the user is a member of an admin group
When the user logs in via SSO
Then the application should retrieve groups from Graph API
And the user's is_admin status should be upgraded to true
And a log entry should indicate "Upgrading is_admin to True for {email} based on SSO admin groups"
Scenario: User with groups overage claim is not in admin group
Given a user with 150 Azure AD group memberships
And the user is NOT a member of any configured admin groups
When the user completes SSO authentication
Then the application should retrieve groups from Graph API
And the user should be created with is_admin=false
And no admin upgrade should occur🙋♂️ User Story 2: Role Mappings with Groups Overage
As a: Platform Administrator managing RBAC via Azure AD groups
I want: SSO_ENTRA_ROLE_MAPPINGS to apply correctly for users with groups overage claims
So that: Users automatically receive appropriate RBAC roles based on their Azure AD group memberships regardless of total group count
✅ Acceptance Criteria
Scenario: User with groups overage receives mapped roles
Given a user with 150 Azure AD group memberships
And the user is a member of groups ["group-admin", "group-developer"]
And SSO_ENTRA_ROLE_MAPPINGS is configured as:
"""
{
"group-admin": "platform_admin",
"group-developer": "developer"
}
"""
And the Azure AD token contains _claim_sources for groups
When the user logs in via SSO
Then the application should retrieve groups from Graph API
And the user should be assigned both "platform_admin" and "developer" roles
And a log entry should indicate role assignments
Scenario: User with groups overage loses role when removed from group
Given a user with groups overage claim has role "developer" from "group-developer"
And the user is removed from "group-developer" in Azure AD
When the user logs in via SSO again
Then the application should retrieve updated groups from Graph API
And the "developer" role should be revoked
And a log entry should indicate "Revoked SSO role 'developer' from {email}"🙋♂️ User Story 3: Graceful Degradation When Graph API Fails
As a: Platform Administrator
I want: The application to handle Graph API failures gracefully without breaking SSO authentication
So that: Users can still log in even if group retrieval fails, with appropriate error logging for troubleshooting
✅ Acceptance Criteria
Scenario: Graph API call fails with 401 Unauthorized
Given a user with groups overage claim
And the Graph API call returns HTTP 401
When the user attempts SSO login
Then the user should still be created/authenticated
And is_admin should remain false (safe default)
And an error log should indicate "Failed to retrieve groups from Graph API: HTTP 401"
And the error log should suggest checking API permissions
Scenario: Graph API call times out
Given a user with groups overage claim
And the Graph API call times out after 30 seconds
When the user attempts SSO login
Then the user should still be created/authenticated
And is_admin should remain false
And an error log should indicate the timeout📐 Design Sketch
Current Behavior (Broken)
sequenceDiagram
participant User
participant Gateway as MCP Gateway
participant EntraID as Azure AD
participant DB as Database
User->>Gateway: SSO Login
Gateway->>EntraID: OAuth Token Exchange
EntraID-->>Gateway: ID Token with _claim_sources (100+ groups)
Gateway->>Gateway: Detect groups overage
Gateway->>Gateway: Log warning, groups=[]
Gateway->>DB: CREATE USER (is_admin=false)
Note over Gateway,DB: ❌ Admin group check fails<br/>❌ Role mappings fail
Gateway-->>User: Login successful (no admin access)
Proposed Behavior (Fixed)
sequenceDiagram
participant User
participant Gateway as MCP Gateway
participant EntraID as Azure AD
participant GraphAPI as Microsoft Graph API
participant DB as Database
User->>Gateway: SSO Login
Gateway->>EntraID: OAuth Token Exchange
EntraID-->>Gateway: ID Token with _claim_sources
Gateway->>Gateway: Detect _claim_sources in token
Gateway->>GraphAPI: POST /users/{id}/getMemberObjects
Note over Gateway,GraphAPI: Use access_token from OAuth
GraphAPI-->>Gateway: {"value": ["group-1", "group-2", ...]}
Gateway->>Gateway: Check groups vs SSO_ENTRA_ADMIN_GROUPS
Gateway->>Gateway: Map groups to roles via SSO_ENTRA_ROLE_MAPPINGS
Gateway->>DB: CREATE USER (is_admin=true, roles assigned)
Note over Gateway,DB: ✅ Admin group check works<br/>✅ Role mappings work
Gateway-->>User: Login successful (admin access granted)
🔗 MCP Standards Check
- Change adheres to current MCP specifications
- No breaking changes to existing MCP-compliant integrations
- If deviations exist, please describe them below:
N/A - This enhancement only affects SSO authentication flow and does not modify any MCP protocol interactions.
🔄 Alternatives Considered
Alternative 1: Azure AD Group Filtering (Attempted - Does NOT Work)
- Approach: Configure
groupMembershipClaims: "ApplicationGroup"and assign only specific groups to the Enterprise Application - Why rejected: Microsoft's documentation reveals a hidden limitation: "Group filtering only applies if a user belongs to 1,000 or fewer groups (including direct and transitive memberships)". Users with 100+ groups still trigger overage even with filtering enabled.
- Evidence: Tested with a user having 100+ memberships, only 1 group assigned to app,
groupMembershipClaims: "ApplicationGroup"configured - still created withis_admin=false.
Alternative 2: Use App Roles Instead of Groups (Limited Use Case)
- Approach: Create Azure AD App Roles (e.g., "admin" role), assign groups to roles, use
SSO_ENTRA_GROUPS_CLAIM: "roles" - Why rejected: Only works for simple single-role scenarios. Doesn't support
SSO_ENTRA_ROLE_MAPPINGSwith multiple group-to-role mappings. Users need different roles from different groups (e.g., admin from one group, developer from another).
Alternative 3: Manual Database Updates (Current Workaround)
- Approach:
UPDATE email_users SET is_admin = true WHERE email = 'user@domain.com' - Why rejected: Not scalable, requires manual intervention for each user, breaks on re-login if user is deleted/recreated.
Alternative 4: Reduce User's Group Memberships (Not Practical)
- Approach: Remove user from unnecessary Azure AD groups to get below overage threshold
- Why rejected: Enterprise users need those groups for other systems (file shares, applications, etc.). Not feasible in large organizations.
📓 Additional Context
Current Code Detection (Already Exists):
The application already detects groups overage on lines 765-772 of mcpgateway/services/sso_service.py:
claim_names = id_token_claims.get("_claim_names", {})
if isinstance(claim_names, dict) and "groups" in claim_names:
logger.warning(
f"Group overage detected for user {user_email} - "
f"token contains too many groups (>200). "
f"Role mapping may be incomplete. Consider using App Roles or Azure group filtering. "
f"See docs/docs/manage/sso-entra-role-mapping.md#token-size-considerations"
)What's Missing: The code detects the problem but doesn't solve it - it just logs a warning and proceeds with empty groups.
Microsoft Documentation:
Affected Code Locations:
- Detection:
mcpgateway/services/sso_service.pylines 765-772 - Groups extraction:
mcpgateway/services/sso_service.pylines 773-775 - Admin check:
mcpgateway/services/sso_service.pylines 1016-1023 (_should_user_be_admin) - Role mapping:
mcpgateway/services/sso_service.pylines 1006-1075 (_map_groups_to_roles)
Test Environment:
- MCP Context Forge Version: 1.0.0-BETA-1
- Deployment: Kubernetes (AWS EKS)
- SSO Provider: Microsoft Entra ID (Azure AD)
- Tenant: Enterprise production environment
- User Group Count: 100+ direct + transitive memberships
- Groups Assigned to App: 1 (admin group)
- Configuration:
groupMembershipClaims: "ApplicationGroup", optional claims with groups
Impact Scope:
- ✅ SSO authentication flow (works)
- ✅ User auto-creation (works)
- ✅ Personal team creation (works)
- ❌ Admin group assignment via
SSO_ENTRA_ADMIN_GROUPS(fails silently) - ❌ Role mappings via
SSO_ENTRA_ROLE_MAPPINGS(fails silently)
Organizations Affected:
- Large enterprises with complex Azure AD structures
- Organizations with 100+ security groups per user
- Teams using Azure AD group-based access control
- Multi-tenant environments with inherited group memberships
Would you accept a pull request for this feature?
Current Behavior
What happens:
- User with 100+ Azure AD groups authenticates via SSO
- Azure AD returns
_claim_namesand_claim_sourcesinstead of directgroupsarray in the token - Application logs warning:
"Group overage detected for user {email} - token contains too many groups (>200)" user_data["groups"]is empty (no groups extracted from token)_should_user_be_admin()fails → user created withis_admin=falsedespite being in admin group_map_groups_to_roles()fails → no RBAC role assignments despite group-to-role mappings
Configuration that fails:
SSO_ENTRA_ADMIN_GROUPS: ["89f32b79-914c-4322-aa3f-6c95765e2073"]Expected Behavior
When groups overage is detected, the application should:
- Check for
_claim_namesand_claim_sourcesin the ID token - Extract the Graph API endpoint from
_claim_sources.src1.endpoint - Call the Microsoft Graph API to retrieve the user's actual group memberships
- Use the retrieved groups for admin checks and role mappings
Technical Details
Token structure with groups overage:
{
"_claim_names": {
"groups": "src1"
},
"_claim_sources": {
"src1": {
"endpoint": "https://graph.microsoft.com/v1.0/users/{user_id}/getMemberObjects"
}
}
}Microsoft Documentation:
Code Location:
- Detection:
mcpgateway/services/sso_service.pylines 765-772 - Groups extraction:
mcpgateway/services/sso_service.pylines 773-775 - Admin check:
mcpgateway/services/sso_service.pylines 1016-1023 - Role mapping:
mcpgateway/services/sso_service.pylines 1006-1075
Reproduction Steps
- Configure Azure AD app with admin group and role mappings
- Authenticate as user with 100+ Azure AD group memberships
- User is created successfully but
is_admin=false - No RBAC roles assigned despite role mappings configuration
Environment
- MCP Context Forge Version: 1.0.0-BETA-1
- Deployment: Kubernetes (AWS EKS)
- SSO Provider: Microsoft Entra ID (Azure AD)
- User Group Count: 100+
Proposed Solution
Add groups overage handling to _get_user_info() method in sso_service.py:
# After detecting groups overage (line 772)
if isinstance(claim_names, dict) and "groups" in claim_names:
user_email = user_data.get("email") or user_data.get("preferred_username") or "unknown"
logger.warning(
f"Group overage detected for user {user_email} - "
f"token contains too many groups (>200). "
f"Calling Graph API to retrieve groups..."
)
# Extract Graph API endpoint from _claim_sources
claim_sources = id_token_claims.get("_claim_sources", {})
src1 = claim_sources.get("src1", {})
groups_endpoint = src1.get("endpoint")
if groups_endpoint:
# Call Graph API to get all groups
from mcpgateway.services.http_client_service import get_http_client
client = await get_http_client()
response = await client.post(
groups_endpoint,
json={"securityEnabledOnly": False},
headers={"Authorization": f"Bearer {access_token}"}
)
if response.status_code == 200:
groups_data = response.json()
user_data["groups"] = groups_data.get("value", [])
logger.info(f"Retrieved {len(user_data['groups'])} groups from Graph API for {user_email}")
else:
logger.error(f"Failed to retrieve groups from Graph API: HTTP {response.status_code}")Workarounds
Current workarounds available to users:
-
Manual admin assignment:
UPDATE email_users SET is_admin = true WHERE email = 'user@domain.com';
-
Azure AD Group Filtering:
- Configure Azure AD to only emit specific security groups in the token
- Reduces group count to avoid overage threshold
-
App Roles (limited):
- Use Azure AD App Roles instead of groups for admin-only scenarios
- Doesn't work if you need multiple group-to-role mappings
Impact
Affected Features:
- ✅ SSO authentication (works)
- ✅ User auto-creation (works)
- ✅ Personal team creation (works)
- ❌ Admin group assignment (
SSO_ENTRA_ADMIN_GROUPS) - ❌ Role mappings (
SSO_ENTRA_ROLE_MAPPINGS)
User Impact:
- Organizations with large Azure AD deployments (100+ groups per user)
- Enterprise environments with complex RBAC requirements
- Silent failure - users created without proper permissions
Additional Context
The warning message on line 768-772 suggests using App Roles or Azure group filtering, but:
- App Roles don't support multiple group-to-role mappings (users need different roles from different groups)
- Group filtering is a manual Azure AD configuration burden for each deployment
Implementing groups overage handling would provide a better out-of-box experience for enterprise Azure AD environments.
Related Files
mcpgateway/services/sso_service.py- SSO service implementationdocs/docs/manage/sso-entra-role-mapping.md- Entra role mapping documentation (referenced in warning)
Would you accept a pull request for this feature?