Working with Microsoft Azure and Microsoft 365, Azure Active Directory as an identity and management system becomes more and more important. Like Active Directory, Azure AD grows throughout time with guest accounts, cloud accounts and synchronized accounts. From a governance and lifecycle point of view - and also for security reasons - it is therefore important to clean up Azure AD from time to time. The cleanup process supports a healthy lifecycle management. In this article we describe how to quickly identify guest users in your own Azure AD with on-board resources.
The goal
We want to identify all guest users and their account status - is their guest invitation pending, or accepted. We also want to find out when a user was last logged in to identify inactive users (to eventually remove them). In this sample, we use a M365 demo tenant and demo accounts. So, we invite some guest users to our tenant in the Azure portal at portal.azure.com.
The Microsoft 365 admin center - Guest users page lists all guest users in a nice and clear way.
Using Microsoft Graph (Explorer)
Well, Microsoft Graph helps us here. We use Microsoft Graph Explorer for this, which provides a quick way to identify guest users and their status in a M365 tenant. Open https://aka.ms/ge and sign-in. For reading, your account must have at least Directory.Read.All and User.Read.All permissions or another role with access to users to get the data we are interested in.
Get all guest users
When we ask for guest users with the following OData query, we get all (or the first page of) guest users with their default properties, like displayName, jobTitle, userPrincipalName, id, and so on.
https://graph.microsoft.com/v1.0/users/?$filter=userType eq 'Guest'
Get more user data
This first query is basically useful, but we are interested in the guest status as well: Has the guest user accepted the invitation? Unfortunately, the Graph OData query methods (still) does not understand a "query all possible properties" like "?$select=*". So, we have to add the field names we want to get with a OData query like "?$select=userPrincipalName,displayName", etc.
How do we get these user properties? Well the Graph Beta endpoint can help here. The same query using the Beta endpoint (currently) delivers much more user properties out of the box.
https://graph.microsoft.com/beta/users?$filter=userType eq 'Guest'
Here, we see that there are useful user properties which deliver our desired information.
The property externalUserState shows our required property if a user has accepted the invitation, or not.
Get all guest users with their status
With that knowledge, we can ask just for the required data (against the v1.0 endpoint again):
https://graph.microsoft.com/v1.0/users/?$filter=userType eq 'Guest'
&$select=userPrincipalName,userType,externalUserState
Well, perfect. In this sample we see that there´s only one guest user (the second item) who has accepted the invitation to our M365 tenant.
So, we can identify that one single guest user is validated (externalUserState is Accepted), while the other guest user(s) did not even accept the invitation to our M365 tenant (externalUserState is PendingAcceptance). To get the last login date, we can add the property signInSessionsValidFromDateTime to our query, as follows.
https://graph.microsoft.com/v1.0/users/?$filter=userType eq 'Guest'
&$select=userPrincipalName,userType,externalUserState,signInSessionsValidFromDateTime
Then we also receive the information when the user last logged in to our organization.
Here one user has logged-in today, while the other user did last sign-in about 2 months ago (and obviously has been re-invited). So, this data can be useful to identify active and old user accounts for further actions.
Update: Get (in)active users
To show if an account is enabled or blocked, we add the accountEnabled property to the select query, as here.
https://graph.microsoft.com/v1.0/users/?$filter=userType eq 'Guest'
&$select=userPrincipalName,userType,externalUserState,signInSessionsValidFromDateTime,accountEnabled
Enabled accounts are shown with a true value, inactive accounts with a false value. The query is now complete.
Summary
With Microsoft Graph, it is easy to quickly identify guest users. Of course, this is just a simple way of obtaining data for further processing. In real life, you would like to automate such processes with ready-to-use apps or processes.
To do some self promotion here, our Governance Toolkit 365 provides such and much more data in a secure and clean way to automate processes. I hope this quick article helps to show how simple it is to work with Microsoft Graph for specific use cases, such as discovering active and inactive guest users in your organization.