Skip to content

fix: use checkMemberGroups for security group membership#1383

Open
damsleth wants to merge 1 commit into
devfrom
fix/msgraph-check-member-groups
Open

fix: use checkMemberGroups for security group membership#1383
damsleth wants to merge 1 commit into
devfrom
fix/msgraph-check-member-groups

Conversation

@damsleth
Copy link
Copy Markdown
Member

Summary

  • Replaces MSGraphService.isUserMemberOfSecurityGroup with a single POST /users/{mail}/checkMemberGroups call. The previous implementation fetched only the first page of /groups/{id}/members and scanned locally, silently denying legitimate members in groups larger than the default page size (~100).
  • The new call is O(1) and transitive, so nested-group membership is handled correctly too.
  • Adds a debug() log on catch so operational failures (permission/consent issues, transient Graph errors) are visible instead of returning false silently.
  • Public signature and return contract are unchanged: (groupId, mail) => Promise<boolean>.

Graph permission requirement

checkMemberGroups requires User.Read.All or Directory.Read.All application/delegated permission. MICROSOFT_SCOPES in .env.sample already includes user.read.all, so no scope change is required for standard deployments. If a tenant's app registration is missing that permission, the endpoint will 403 and the catch will log + return false (fail-closed, same as today). The added debug log makes this diagnosable.

Files changed

  • server/services/msgraph/MSGraphService.ts - new implementation + debug import
  • server/services/msgraph/MSGraphService.test.ts - new, stubs the Graph client and covers member/non-member/error/url-encoding paths

Test plan

  • npm run lint passes
  • npm test - the four new isUserMemberOfSecurityGroup cases pass in isolation. Note: several pre-existing tests (ReportService.test.ts, passport/index.test.ts, timesheet/extensions.test.ts) fail compilation under ts-node with TS2694: Namespace 'global.Express' has no exported member 'User' on this worktree. This is unrelated to this change (reproduces on clean origin/dev) and appears to pre-date this PR; flagged here for awareness.
  • Manual sign-in smoke test with a small security group - confirm existing member still signs in.
  • Manual sign-in smoke test with a group that has >100 members - previously broken, should now succeed.

Out of scope

  • checkSecurityGroupMembership.ts caller shape (separate plan).
  • Widening the signature to accept user IDs (callers only have mail).
  • Caching (call is one-per-sign-in and fast).

Replace the paged /groups/{id}/members scan with a single
/users/{mail}/checkMemberGroups POST. The previous implementation
only read the first page (default 100 members), silently denying
legitimate members in larger security groups. checkMemberGroups
is O(1) and transitive, and the caller surface stays the same
(groupId, mail) -> Promise<boolean>.

Also add a debug() log on catch so operational failures (e.g.
missing Directory.Read.All / User.Read.All consent) are
diagnosable instead of silently returning false.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant