Microsoft 365, Entra and Intune
Microsoft 365 guest user cleanup: 340 externals, 12 of whom you can name
Filter the user list by external and the number is always higher than expected. Three hundred and forty, in a company of forty. You can name twelve of them. About sixty have email addresses at domains you do not recognise, and at least one is a personal Gmail address invited to a SharePoint folder in 2021.
Microsoft 365 guest user cleanup is one of those jobs where the naive approach is actively dangerous, because the obvious signal for "this guest is inactive" is wrong in a way that takes real customers with it.
Where the 340 came from
Nobody sat down and invited three hundred people. They arrived through four routes, all of which are working as designed.
Teams meeting invitations. An external participant in a Teams meeting can end up as a guest object depending on tenant settings and how they joined. A year of customer calls produces a lot of these.
SharePoint and OneDrive sharing. The most productive source. Anyone with sharing rights sends a link to an external address, and a guest object appears. The person sharing had no idea they were creating a directory object, and they were not doing anything wrong.
Teams channel membership, where somebody adds an external collaborator to a project team. Correct at the time, and the team outlives the project.
Application and integration invitations. A vendor's support engineer invited during onboarding, still there two years later.
None of these routes has an exit. There is no process that removes a guest when the project ends, because no system knows the project ended.
Why last sign-in is the wrong signal for microsoft 365 guest user cleanup
This is the part worth getting right before you delete anything, and it is the mistake I have actually made.
The obvious query sorts guests by last successful sign-in and treats a distant date as evidence of dormancy. It is not reliable, because a B2B guest can access your resources in ways that do not produce an interactive sign-in record against your tenant in the way you would expect. Their home tenant authenticates them. Depending on the resource and the access path, your view of their activity can show nothing while they are using a shared document weekly.
Delete on that basis and you remove live client contacts. It reads as a tidy-up in your logs and as an access failure in their inbox, and the first you hear of it is an email asking why a link stopped working. Deleted guest objects can be restored within a window, but the access grants that referenced them are messier to reconstruct.
So treat the sign-in date as a prompt to investigate rather than a verdict. The signals worth combining:
What do they actually have access to. A guest with no group memberships and no resource permissions is genuinely removable regardless of dates. A guest who is a member of an active Team is not, whatever the sign-in data says.
Who invited them, and is that person still here. The inviter is recorded on the guest object. A guest invited by a leaver, for a project that finished, with no current memberships, is the clear case.
Does the domain still matter. A guest at a domain you no longer do business with is a different conversation from one at your largest customer.
Ask. For anything ambiguous, one message to the internal person who owns that relationship resolves it in minutes. This is slower than a query and it is the difference between a cleanup and an incident.
The review that works
Quarterly, in three passes, most restrictive first.
Pass one: guests with no memberships and no permissions. These are pure residue. Remove them. No conversation needed because there is nothing to remove access to.
Pass two: guests whose inviter has left. Find the current internal owner of that relationship. If nobody claims it, remove. If somebody does, record who and move on.
Pass three: everything else, by domain. Group by email domain and review by relationship rather than by person. "Are we still working with this company" is a question somebody can answer, whereas "should Sarah at this domain still have access" usually is not.
Entra access reviews can automate the mechanics of this, including asking the inviter to attest, and they produce the dated record an auditor wants. Microsoft's access review documentation covers the licensing, which needs P2 for the automated version, the same gate as PIM.
Without P2 the manual version is a spreadsheet and an afternoon, and it counts just as much provided you write down what you decided.
Stopping the inflow
Cleaning up without changing the sharing policy means doing this again next quarter with similar numbers.
The settings worth changing, none of which stop legitimate work:
Default sharing links to "specific people" rather than "anyone". Anonymous links do not create guest objects but they also cannot be reviewed, which is worse. Specific-people links create a reviewable object.
Set an expiry on guest access where your licensing supports it, so access lapses by default and has to be renewed deliberately.
Restrict who can invite guests. Not to administrators only, which creates a bottleneck people route around, but not to everyone either.
Turn off guest creation from Teams meetings if you do not need it, which most companies do not.
The one to resist is disabling external sharing entirely. Somebody will need to send a file to a customer, and if the platform will not let them they will use personal email or a consumer file service, which removes the visibility you were trying to gain.
Where this sits
Guests are one of the categories in the Conditional Access set, where restricting what a guest can reach is a policy rather than a review. The two work together: policy limits the blast radius, review removes what is no longer needed.
If a customer questionnaire has asked you about third-party access, this is the control they mean, and it is one of the security and compliance areas where the evidence is usually missing rather than the practice.