Guest User Access Review
Monthly flow that reviews all guest users in Azure AD, checks their last sign-in date, and sends a report to IT admins. Flags inactive guests (90+ days) for removal and sends removal approval requests.
Provided as-is, without warranty of any kind. Review and test each pattern in a non-production environment before deploying it to live automations. See our Terms.
Overview
Guest User Access Review is a scheduled compliance flow that runs once a month and audits every guest user in Azure Active Directory. It queries Microsoft Graph for the full guest user list, calculates how many days have passed since each guest last signed in, and categorizes accounts as active or inactive based on a 90-day threshold. Results are logged to a SharePoint list for an auditable trail, a summary report is emailed to IT admins, and an approval request is raised for each inactive guest so an admin can decide whether to disable the account via Graph API. The flow is designed to give security and compliance teams a low-maintenance, recurring control over external collaboration access.
Use Case
Many tenants accumulate guest users from one-off SharePoint shares, Teams invitations, and project collaborations — and most of those accounts stay active long after the project ends. This flow gives IT and security teams a monthly, automated checkpoint to surface stale guest accounts, document the review (for SOC 2, ISO 27001, or internal audit evidence), and route removals through a lightweight approval rather than a script that silently deletes accounts. Because every step is logged to SharePoint and emailed to admins, the review doubles as the compliance artifact auditors typically ask for.
The flow is ideal for teams that:
- IT and security teams that need recurring guest-access reviews for compliance (SOC 2, ISO 27001, internal audit).
- Tenants with a high volume of external collaborators via Teams and SharePoint sharing.
- Organizations that want approval-gated guest removal rather than silent deletion.
- Admins who want a single auditable SharePoint list as the system of record for guest reviews.
Flow Architecture
Monthly schedule
RecurrenceRuns once per month at 06:00 to keep guest-access reviews on a predictable cadence. Frequency: Month, Interval: 1, At these hours: 6.
Get all guest users
HTTP (Microsoft Graph)Calls Microsoft Graph: GET https://graph.microsoft.com/v1.0/users?$filter=userType eq 'Guest'&$select=displayName,mail,signInActivity,createdDateTime to return every guest account in the tenant along with its last sign-in activity.
Parse JSON response
Parse JSONParses the Graph response into a typed object so downstream actions can address fields like displayName, mail, and signInActivity.lastSignInDateTime.
For each guest — categorize by activity
Apply to eachLoops through every guest, calculates days since last sign-in, and routes each account into an Active or Inactive collection based on a 90-day threshold.
If days since last sign-in > 90
If conditionSplits guests into active vs inactive buckets so only stale accounts get flagged for removal review.
- Append to array variable — Adds the guest object to the inactive guests collection used by the removal-approval loop.
For each guest — log to SharePoint
Apply to eachIterates over every reviewed guest and writes a row to the 'Guest Access Review' SharePoint list capturing Guest Name, Email, Last Sign-In, Status, and Review Date for the audit trail.
Environment Variables
| Schema name | Type | Default | Description |
|---|---|---|---|
| flowlibs_GuestInactivityThresholdDays | Number | 90 | Number of days since last sign-in before a guest is flagged as inactive and routed to the removal-approval loop. |
| flowlibs_ReviewSharePointSiteUrl | String | https://your-tenant.sharepoint.com/sites/<configure> | SharePoint site that hosts the 'Guest Access Review' list used as the audit log. |
| flowlibs_ReviewSharePointListName | String | Guest Access Review | Display name of the SharePoint list that stores each guest's review record. |
| flowlibs_ITAdminEmail | String | alerts@yourcompany.com | Distribution list or mailbox that receives the monthly review report email. |
| flowlibs_GraphApiBaseUrl | String | https://graph.microsoft.com/v1.0 | Base URL for Microsoft Graph calls — override only if you need to target a sovereign cloud (e.g. graph.microsoft.us). |
Connectors & Connections
| Connector | API name | Actions used |
|---|---|---|
| HTTP with Microsoft Entra ID (Azure AD) | shared_httpwithazureadtoken | InvokeHTTP (Calls Microsoft Graph to list and disable guest users) |
| Office 365 Outlook | shared_office365 | SendEmailV2 (Sends the monthly review report to IT admins) |
| SharePoint | shared_sharepointonline | PostItem (Creates one item per reviewed guest in the audit list) |
| Approvals | shared_approvals | StartAndWaitForAnApproval (Requests admin approval before disabling each inactive guest) |
Note — All connections are referenced as solution connection references; the flow is portable between environments as long as a connection is mapped at import time.
Customization Guide
Almost every realistic variant of this flow can be implemented by changing environment variable values. A few cases require small edits inside the flow definition — those are called out explicitly below.
- Tune the inactivity threshold
- The 90-day window is a reasonable default for most tenants, but compliance-heavy environments may prefer 30 or 60 days. Update the flowlibs_GuestInactivityThresholdDays environment variable rather than editing the condition expression — this keeps the policy auditable and lets you change it without re-importing the solution.
- Add team-owner verification
- Before raising the removal approval, branch on whether the guest has membership in any Microsoft 365 group and route a 'do you still need this guest?' approval to that group's owner first. This avoids surprising business owners when a guest they rely on disappears.
- Include access context in the report
- Enrich each guest row with the Teams and SharePoint sites they currently have access to (via Graph /users/{id}/memberOf and /users/{id}/joinedTeams). The extra context helps admins decide whether removal is safe.
- Track review completion for compliance
- Add a 'Reviewed By' and 'Decision' column to the SharePoint list and update them when the approval response comes back. The list then becomes the evidence artifact auditors ask for in SOC 2 / ISO 27001 user-access reviews.
- Soft-disable before delete
- Instead of DELETE-ing the guest in the approved branch, PATCH accountEnabled to false and tag the account for hard-delete after a 30-day grace period. This gives you a window to recover if a removal turns out to be a mistake.
Key Expressions
The flow is intentionally light on Power Fx / WDL gymnastics — the heaviest expressions are the branch-name concatenation and the approval outcome check. They are listed below in the order they appear in the flow.
EXPR.01Days since last sign-in
Inside the Apply to each: computes the number of whole days between now and the guest's last sign-in. Falls back to createdDateTime when the guest has never signed in.
EXPR.02Inactive threshold check
The If-condition expression that routes a guest into the inactive bucket when their days-since-last-sign-in exceeds the configured threshold.
EXPR.03Graph users filter URL
Builds the Graph request URL from the configurable base URL so the flow works against sovereign clouds without code edits.
Comments
Sign in to join the conversation.
Sign inNo comments yet. Be the first to share your experience with this flow.