I believe that a lot of you have questions about Guest user lifecycle and what is the best ways to handle this. There is no unified solution for guest lifecycle as usage of Guest accounts from tenant to tenant is really different. Guest users can be used for for example for Teams collaboration, SharePoint access, member of a distribution group.
One of the immediately suggested tools is Access Reviews – This is perfect for – at is it called “Access” review, but not Guest account lifecycle. We want to have clean environment and of course narrow down the surface attack. Why should we have any object on the environment which is not in use? Delete, remove.
One of the logical input data for making decision should account be deleted is last sign in date, right?
For some time I have struggled to have data of Guest Users sign in for more than just 30 days ago.
SOLUTION is to use Beta GRAPH Api.
If you first want to read more about it here you are:
- More about signInActivity resource type:
https://docs.microsoft.com/en-us/graph/api/resources/signinactivity?view=graph-rest-beta
- More about managing inactive user accounts:
Here is Script in Powershell that I have used to get info on all of my tenant`s Guest accounts last log in time (Of course feel free to make this script better, nicer, quicker or what ever and share it with us):
# We need to have Microsoft ADAL Powershell Module Loaded"
Write-Output "Loading Microsoft ADAL Powershell Module..."
try {Import-Module Microsoft.ADAL.Powershell } catch {Write-Output $_}
$tenantID = "Enter Your Tenant ID"
$authString = "https://login.microsoftonline.com/$tenantID"
$appId = "Enter Your App Registration ID"
$appSecret = "Enter Your App Registration Secret"
# this part uses the classes to obtain the necessary security token for performing our operations against the Graph API
$creds = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential" -ArgumentList $appId, $appSecret
$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext"-ArgumentList $authString
$context = $authContext.AcquireTokenAsync("https://graph.microsoft.com/", $creds).Result
$token=$context.AccessToken
Function Get-Headers {
param( $token )
Return @{
"Authorization" = ("Bearer {0}" -f $token);
"Content-Type" = "application/json";
}
}
$headers=Get-Headers($token)
#After we have token we are getting ALL Guest accounts:
$AllGuestUsers= "https://graph.microsoft.com/beta/users?$filter=userType eq 'Guest'"
do
{
$myReport = (Invoke-WebRequest -UseBasicParsing -Headers $headers -Uri $AllGuestUsers)
$convertedReport += ($myReport.Content | ConvertFrom-Json).value
$AllGuestUsers = ($myReport.Content | ConvertFrom-Json).'@odata.nextLink'
}
while($AllGuestUsers -ne $null)
# Query each guest account for Last SignIn
foreach ($guestAccount in $convertedReport)
{
$GuestObjectID=$null
$GuestObjectID=($guestAccount).id
$convertedSignInReport=$null
$SignInReport=$null
$lastsign=$null
$SigninActivity= "https://graph.microsoft.com/beta/users/$GuestObjectID`?`$select=signInActivity"
$SignInReport = (Invoke-WebRequest -UseBasicParsing -Headers $headers -Uri $SigninActivity)
$convertedSignInReport = ($SignInReport.Content | ConvertFrom-Json).value.signInActivity.lastSignInDateTime
if ($convertedSignInReport) {$lastsign=(get-date $convertedSignInReport -Format "yyy-MM-dd")} else {Write-Host "No Sign In data for "$guestAccount.displayName"" -BackgroundColor Red -ForegroundColor White}
$obj = New-Object PSObject
$obj | Add-Member -membertype NoteProperty -name "DisplayName" -value $guestAccount.displayName
$obj | Add-Member -membertype NoteProperty -name "ObjectId" -value $guestAccount.id
$obj | Add-Member -MemberType NoteProperty -Name "UserPrincipalName" -Value $guestAccount.userPrincipalName
$obj | Add-Member -MemberType NoteProperty -Name "Mail" -Value $guestAccount.mail
$obj | Add-Member -membertype NoteProperty -name "LastLogIn" -value $lastsign #(get-date $convertedSignInReport -Format "yyy-MM-dd")
$obj
[array]$completeReport+=$obj
}
Thank you for reading this article and I hope it will be helpful for you.
Regards,
Ivan