Every tenant has that one script. It runs at 6 a.m., dumps a list of who’s in which groups, and feeds an access review, a license report, or an app that provisions people into SharePoint. And somewhere near the top of it is a call that expands memberOf on a user. It has worked for years. Nobody’s touched it. So a deprecation notice for memberOf lands like a boot through a window.
Let’s do the drill. What’s actually changing, how scared you should be, and what to write instead.
What memberOf does, and why half your automation leans on it
memberOf is a navigation property in Microsoft Graph. Point it at a user, a service principal, or a device, and it answers the reverse question: not “who’s in this group” but “which groups is this object in.” That reverse lookup is the whole reason it’s everywhere. Group membership in Entra is stored on the group as a list of members; asking a user what they belong to means walking the directory the other direction, and memberOf is the shortcut that hides the walk.
Plain memberOf returns direct memberships only. If Ana is in “Engineering” and “Engineering” is nested inside “All Staff,” memberOf shows you Engineering and stops. It also returns more than groups — directory roles and administrative units come back in the same collection, which is why half of you have a Where-Object filter bolted on to strip out the noise. Yes, groups have a memberOf too (the parent groups a group belongs to), but the query that breaks things in production is almost always the one on users.
The part where my skeptical colleague pushes back
“Hold on. Microsoft is retiring memberOf? The property that a decade of Graph tutorials is built on? I’ll believe it when I see a hard date.”
Good instinct, and keep it. Here’s the honest state of play: the alert is real enough to act on, but I’m not going to hand you an enforcement date I can’t stand behind. If you’re going to tear up working automation, you verify first — not from a blog, not from me. Two places, both authoritative:
- The Microsoft Graph changelog, filtered to the
Deprecationcategory. A genuine retirement shows up there with the resource, the property, and a target date. - Your Message Center in the Microsoft 365 admin center, which is where a change with tenant-wide blast radius gets an MC ID and a timeline you can forward to your change board.
If it isn’t in both, it’s noise. Until Microsoft publishes a date, treat this as a fire drill, not a fire — but run the drill, because the migration is worth doing whether the deadline is next quarter or never.
“Fine, but if there’s no confirmed date, why should I rewrite anything today?”
Because memberOf is the wrong tool for most of the jobs it’s doing, and the deprecation chatter is just the excuse to fix it. Most scripts that expand memberOf actually want transitive membership — they want nested groups resolved — and they’ve been silently returning incomplete results for years. Direct-only means the person who inherits access through a nested group never shows up in your report. That’s not a future breaking change. That’s a bug you shipped in 2021.
“So the thing everyone’s panicking about might actually be doing me a favour.”
Now you’re getting it.
The three replacements, and when each one is right
Microsoft doesn’t give you one drop-in swap. It gives you three tools, and choosing wrong is how you end up with a “fix” that’s slower or subtly incomplete.
getMemberGroups— a POST action. Returns group IDs only, and returns them transitively (nested groups included). This is your answer for “does this user have access, yes or no?” — authorization checks, filtering, membership tests. It’s fast and it scales because it hands back a flat list of GUIDs and nothing else. If all you need is IDs to compare against, this is the one.transitiveMemberOf— a navigation property. Returns full objects, transitively, including groups, directory roles, and administrative units. Use it when you need display names, group types, or other properties in the output — reports a human reads. You pay for the richness in payload size and speed.getMemberObjects— likegetMemberGroupsbut also returns directory roles and administrative units as IDs. Reach for it only when you genuinely need those.
The rule of thumb: need a yes/no or a set of IDs, use getMemberGroups; need a readable report with names, use transitiveMemberOf. Notice that neither one is a literal replacement for old memberOf behaviour, because old memberOf was direct-only. If you have a script that genuinely depends on direct membership and not nested, that’s the one edge case where you want Get-MgGroupMember against the specific group instead of a reverse lookup at all.
The side-by-side
The old pattern — expanding memberOf on a user. It works today, it returns direct memberships only, and it’s the shape of query the deprecation notice is aimed at:
The new pattern, fast path — getMemberGroups when you only need IDs and you want nesting resolved:
The new pattern, report path — transitiveMemberOf when a human needs names, with pagination handled properly via -All:
Two things to internalise. Old-to-new is not a find-and-replace — you’re switching from direct to transitive membership, and your row counts will change. That’s the correct behaviour, but it’ll set off alarms in any downstream report that reconciles against a stored baseline. Test on a handful of reviewed accounts before you let it near the scheduled job.
How to find what’s exposed before it bites you
You can’t grep the tenant. You can grep everything that talks to it, and that’s where the risk actually lives:
- Search your repos, Azure Automation runbooks, Function Apps, and Logic Apps for the literal strings
memberOf,ExpandProperty memberOf,/memberOf, andGet-MgUserMemberOf. Include the deprecated-module callers too — anything onAzureADorMSOnlineis already a migration you’re overdue on, and this is the nudge to finish it. - Review the API permissions on your app registrations and enterprise apps. Anything third-party doing user-to-group reverse lookups — HR sync, IGA connectors, custom provisioning — is a candidate. Ask the vendor which Graph call they use; if the answer is “expanding memberOf,” open a ticket now, not in six months when their agent shrugs at you.
- Inventory scheduled tasks and cron jobs on servers nobody logs into anymore. That 6 a.m. script has no owner and no test coverage, and it’s the one that’ll page you.
What this touches in the admin center
Almost nothing in the Entra portal itself. The membership blade on a user, the group’s Members list, and Access Reviews all resolve membership server-side through supported paths — clicking around the admin center isn’t calling your soon-to-be-deprecated property. The exposure is entirely in your code and your third-party integrations. Which is the uncomfortable part: there’s no red banner in the portal warning you. The blast radius is the automation you can’t see from the UI.
Run the audit this week. Rewrite the reverse lookups on your own schedule, not Microsoft’s. And when you do, fix the nesting bug you’ve been shipping while you’re in there — because the version of this story where you rush a bad swap under deadline pressure is the one that actually takes down access reviews. Confirm the date in the changelog, then move deliberately. The property isn’t gone tomorrow. Your excuse for the broken report will be.
