You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Enhancement]: Option to sync only Entra ID groups already referenced by ACLs #16633
An opt-in env flag, ENTRA_ID_SYNC_ONLY_REFERENCED_GROUPS, that limits login-time Entra group sync to groups LibreChat already has, and deletes an Entra group once no ACL entry references it.
With the flag on:
Login adds and removes the user only on entra groups already in the groups collection; it does not create new ones.
Revoking the last ACL entry for an entra group, or deleting the resource that held it, deletes the group.
Groups are still created when someone shares a resource with them, as today (ensureGroupPrincipalExists fetches members from Graph at that point).
Default behavior is unchanged.
More details
Since #12606, syncUserEntraGroupMemberships creates a Group for every Entra group the user belongs to. In a large tenant that is thousands of groups never used for sharing, and every one the user is a member of becomes a principal in the $or of each ACL query. On DocumentDB we saw these queries take up to ~60s. #16233 reports the same fan-out (280+ groups per user) driving OOMs on Cosmos DB.
Narrowed scope: the PR adds only the creation gate, as ENTRA_ID_SYNC_ONLY_EXISTING_GROUPS. Deleting a group once its last ACL entry goes is left out, because groups are also referenced by admin config overrides, system grants and MCP authority.
I traced this against current dev. The creation gate in #16638 looks right to me. Two things affect whether it fixes the slowdown described here:
Groups created by earlier syncs stay in the principal list. getUserPrincipals (packages/data-schemas/src/methods/userGroup.ts) adds a GROUP principal for every group whose memberIds contains the user, whether or not any ACL entry references it. With the flag on, no new groups are added, but a tenant that already synced thousands of groups since 🪪 feat: Optimized Entra ID Group Sync with Auto-Creation #12606 keeps the same $or until those groups are removed. That applies to the DocumentDB and Cosmos cases here and in [Bug]: ACL permission checks scale multiplicatively with PermissionBits enum size × principal count, causing severe CPU/memory load on Cosmos DB/DocumentDB with large group-based ACLs #16233. You were right to drop auto-delete, since groups are also referenced from aclentries, configs and systemgrants (principalType: 'group') and from MCP authority. A dry-run-by-default cleanup script that lists entra groups referenced by none of those would let existing deployments see the improvement. Or the PR's risk section could say that the flag only helps new tenants unless the groups are pruned.
With the flag on, share-time membership has to be reliable, and today it isn't. Once login sync stops creating groups, ensureGroupPrincipalExists (api/server/services/PermissionService.js) is the only place a group gets members before each member logs in again. getGroupMembers (GraphApiService.js) catches every error, including 429 throttling and missing GroupMember.Read.All consent, and returns []. ensureGroupPrincipalExists then:
creates a new group with memberIds: [], so no one in it can see the shared resource until each person logs in again, and
for an existing group, sets updateData.memberIds = memberIds whenever an authContext is present, so a failed fetch while re-sharing replaces the group's member list with [].
This bug also exists without the flag, but there login sync quickly re-adds everyone, so it rarely shows. With the flag on, it's the main way members get added. A small fix would be to have getGroupMembers throw, or return null, on failure, and to leave memberIds unchanged in that case. That probably belongs in #16638 or a follow-up next to it, with a test for the throttled-fetch case.
Activity
jtodaroii commentedon Oct 1, 2026
Narrowed scope: the PR adds only the creation gate, as
ENTRA_ID_SYNC_ONLY_EXISTING_GROUPS. Deleting a group once its last ACL entry goes is left out, because groups are also referenced by admin config overrides, system grants and MCP authority.mehran-almma commentedon Oct 8, 2026
I traced this against current dev. The creation gate in #16638 looks right to me. Two things affect whether it fixes the slowdown described here:
Groups created by earlier syncs stay in the principal list. getUserPrincipals (packages/data-schemas/src/methods/userGroup.ts) adds a GROUP principal for every group whose memberIds contains the user, whether or not any ACL entry references it. With the flag on, no new groups are added, but a tenant that already synced thousands of groups since 🪪 feat: Optimized Entra ID Group Sync with Auto-Creation #12606 keeps the same $or until those groups are removed. That applies to the DocumentDB and Cosmos cases here and in [Bug]: ACL permission checks scale multiplicatively with PermissionBits enum size × principal count, causing severe CPU/memory load on Cosmos DB/DocumentDB with large group-based ACLs #16233. You were right to drop auto-delete, since groups are also referenced from aclentries, configs and systemgrants (principalType: 'group') and from MCP authority. A dry-run-by-default cleanup script that lists entra groups referenced by none of those would let existing deployments see the improvement. Or the PR's risk section could say that the flag only helps new tenants unless the groups are pruned.
With the flag on, share-time membership has to be reliable, and today it isn't. Once login sync stops creating groups, ensureGroupPrincipalExists (api/server/services/PermissionService.js) is the only place a group gets members before each member logs in again. getGroupMembers (GraphApiService.js) catches every error, including 429 throttling and missing GroupMember.Read.All consent, and returns []. ensureGroupPrincipalExists then:
creates a new group with memberIds: [], so no one in it can see the shared resource until each person logs in again, and
for an existing group, sets updateData.memberIds = memberIds whenever an authContext is present, so a failed fetch while re-sharing replaces the group's member list with [].
This bug also exists without the flag, but there login sync quickly re-adds everyone, so it rarely shows. With the flag on, it's the main way members get added. A small fix would be to have getGroupMembers throw, or return null, on failure, and to leave memberIds unchanged in that case. That probably belongs in #16638 or a follow-up next to it, with a test for the throttled-fetch case.